Chapter 4: Data Formats 159
PART I
You can verify for yourself that this technique works in Firefox, Opera, and Safari using
the example at http://ajaxref.com/ch4/xmlxhtmlresponse.html. However, at this point it
doesn’t work in Internet Explorer 6 and 7, so if you really must use getElementById()
style access to XML content, you are better off passing around some form of XHTML using
id and class values on <div> and <span> tags to add your semantics. It’s not optimal but
it will work, and it does force well-formedness if you use responseXML and the IE ActiveX
DOM parser.
You can try to write your own DTD or Schema with an id attribute properly defined.
However if you do so, remember lessons learned earlier. Firefox will not look at an external
DTD, so be sure to include the DTD internally. Second, MSXML2.DOMDocument.6.0 will not
load any DTDs at all, so be sure to use the older MSXML2.DOMDocument.3.0. You can then
stuff the DTD into your payload making your response packet look something like this:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pollresults [
<!ELEMENT pollresults (rating,average,votes)>
<!ELEMENT rating (#PCDATA)>
<!ELEMENT average (#PCDATA)>
<!ELEMENT votes (#PCDATA)>
<!ATTLIST rating id ID #IMPLIED>
<!ATTLIST average id ID #IMPLIED>
<!ATTLIST votes id ID #IMPLIED>
]>
<pollresults>
<rating id="rating">5</rating>
<average id="average">3.12</average>
<votes id="votes">1345</votes>
</pollresults>
Now, using our cross-browser approach to provide getElementById() functionality
in all browsers, you have again solved the direct tag access problem. See for yourself at
http://ajaxref.com/ch4/xmlgetelementbyid.html.
Brute Force Solution
If the last few examples have made you cringe in their ugliness, know that you certainly
aren’t alone. It turns out that there may be a better solution in the use of a brute force tree
walking algorithm. Remember that the DOM forms a tree of any returned well-formed
markup. It would be easy enough to do some ordered walk of the tree and check each node
for an id attribute using the DOM’s getAttribute() method.
function bruteGetElementById(id,startNode)
{
var allElements = xmlDoc.getElementsByTagName("*");
for (var j=0; j<allElements.length; j++)
{
if (allElements[j].getAttribute("id") == id)
{
return allElements[j];
break;
}