[ Team LiB ] Previous Section Next Section

14.4 Embedding XML Data

NN 6, IE 5(Win)

14.4.1 Problem

You want to reference XML document data to support script activities in the main page.

14.4.2 Solution

IE 5 or later for Windows and Netscape 6 or later allow you to create an invisible virtual document that holds raw XML data, which your scripts may then traverse using standard DOM node referencing methods and properties. Loading the XML data requires browser-specific handling, but once that occurs, you can reference the content and its node tree uniformly.

The following verifySupport( ) function loads an external XML document (URL passed as a parameter) into a global variable named xDoc and returns a Boolean value indicating whether the browser supports the capability:

var xDoc;
// verify that browser supports XML features and load external .xml file
function verifySupport(xFile) {
    if (document.implementation && document.implementation.createDocument) {
        // this is the W3C DOM way, supported so far only in NN6+
        xDoc = document.implementation.createDocument("", "theXdoc", null);
    } else if (typeof ActiveXObject != "undefined") {
        // make sure real object is supported (sorry, IE5/Mac)
        if (document.getElementById("msxml").async) {
            xDoc = new ActiveXObject("Msxml.DOMDocument");
        }
    }
    if (xDoc && typeof xDoc.load != "undefined") {
        // load external file (from same domain)
        xDoc.load(xFile);
        return true;
    } else {
        var reply = confirm("This example requires a browser with XML support, " +
            "such as IE5+/Windows or Netscape 6+.\n \nGo back to previous page?");
        if (reply) {
            history.back( );
        }
    }
    return false;
}

This function requires one extra helper in the form of an <object> tag at the bottom of the page that attempts to load the ActiveX control (in IE), which makes the actual loading in the function possible in that browser:

<!-- Try to load Msxml.DOMDocument ActiveX to assist support verification -->
<object id="msxml" width="1" height="1" 
    classid="CLSID:2933BF90-7B36-11d2-B20E-00C04F983E60" ></object>

14.4.3 Discussion

On the Internet Explorer side of this solution, an ActiveX control (MSXML) provides the raw XML container and the associated load( ) method. While newer versions of this control are delivered in the most recent browser versions, the code in the Solution uses a backward-compatible version for broader support. The newer browsers continue to provide the older ActiveX control.

The W3C DOM Level 2 doesn't provide for an object that silently loads an XML document needed for this application, but the Mozilla developers filled in the missing pieces. Starting with the W3C DOM document.implementation object and createDocument( ) method, Mozilla added the load( ) method on the document object returned by createDocument( ). But the load( ) method could be improved because you may find that XML documents recognized by the method must be from the same directory as the page invoking the call. In any case, both the IE and Mozilla load( ) methods require that the source material be from the same server and domain to keep security policies in good order. Thus, don't look upon this solution as a way for the client to scrape XML data from other sources (something server programming can do nicely).

The reason that you need to load XML into these separate virtual documents is that loading them into a browser frame (hidden or visible) causes most browsers to HTML-ize the document. In the case of IE, the browser performs all kinds of formatting on the content so that it renders in the browser window with a variety of colors, indenting, and hierarchy symbols. The node tree of the raw document is buried and commingled with the browser-created window dressing. Other browsers typically treat the XML as body content of a standard HTML page, whereby tags for the html, head, and body elements become part of the document tree, like it or not. If your XML contains elements with those tag names (very common for the head and body elements), scripts that need to traverse the DOM node tree will have an impossible time.

The Solution is fashioned as a function that returns a Boolean value indicating whether the XML loading is successful or supported by the browser. The deployment plan includes another function that uses the returned value as a switch to invoke action on the XML document's content or bypass it. To keep IE from racing ahead with operating on the document before it has loaded, invoke the operative function via setTimeout( ):

// initialize first time -- invoked onload
function init(xFile) {
    // confirm browser supports needed features and load .xml file
    if (verifySupport(xFile)) {
        // let file loading catch up to execution thread
        setTimeout("operativeFunction( )", 1000);
    }
}
...
<body onload="init('myData.xml');">

Internet Explorer for Windows provides an additional way to embed XML data in a document: the XML data island. IE supports a proprietary <xml> tag set, in which you can place well-formed XML data. Most typically, such data is the result of a database query, returned as a set of XML-formatted records. This format lends itself nicely to either direct transformation to dynamically generated HTML or to JavaScript data (arrays of objects), which scripts then use to generate the HTML and perform operations such as client-side sorting of tabular data.

To prevent the browser from rendering the XML content, use style sheets to set the display style property of the xml element to none. The following is an excerpt from an XML file containing historic World Cup final match results:

<xml id="myData" style="display:none">
<worldcup>
    <final>
        <location>Uruguay</location>
        <year>1930</year>
        <winner>Uruguay</winner>
        <winscore>4</winscore>
        <loser>Argentina</loser>
        <losscore>2</losscore>
    </final>
    <final>
        <location>Italy</location>
        <year>1934</year>
        <winner>Italy</winner>
        <winscore>2</winscore>
        <loser>Czechoslovakia</loser>
        <losscore>1</losscore>
    </final>
    ...
</worldcup>
</xml>

Scripts can access elements or groups of elements in the data island via standard DOM node tree accesses. For example, to obtain an array of final elements from the previous example, use the following statement:

var allCups = document.getElementById("myData").getElementsByTagName("final");

14.4.4 See Also

Recipe 14.6 for generating an HTML table from XML data; Recipe 14.8 for creating JavaScript custom objects from XML data; Recipe 14.17 for walking a document node tree for XML or HTML documents.

    [ Team LiB ] Previous Section Next Section