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.
|