Our first step will be to load an XML document into Internet Explorer using code, and to create a document object. Using this object, we'll be able to access all aspects of the document itself.
As mentioned earlier in this chapter, there are two ways to load an XML document into Internet Explorer so that you have access to it using JavaScript. To see how this works, I'll use this XML document, meetings.xml, throughout this chapter—this document records business meetings, including who was present and when the meeting occurred:
<?xml version="1.0"?> <MEETINGS> <MEETING TYPE="informal"> <MEETING_TITLE>XML In The Real World</MEETING_TITLE> <MEETING_NUMBER>2079</MEETING_NUMBER> <SUBJECT>XML</SUBJECT> <DATE>6/1/2002</DATE> <PEOPLE> <PERSON ATTENDANCE="present"> <FIRST_NAME>Edward</FIRST_NAME> <LAST_NAME>Samson</LAST_NAME> </PERSON> <PERSON ATTENDANCE="absent"> <FIRST_NAME>Ernestine</FIRST_NAME> <LAST_NAME>Johnson</LAST_NAME> </PERSON> <PERSON ATTENDANCE="present"> <FIRST_NAME>Betty</FIRST_NAME> <LAST_NAME>Richardson</LAST_NAME> </PERSON> </PEOPLE> </MEETING> </MEETINGS>
The first way of loading an XML document into Internet Explorer is to create a document object using the Microsoft.XMLDOM class.
To see this in action, I'm going to create an example that reads in meetings.xml and retrieves the name of the third person in that document (Betty Richardson). I start by creating a new document object like this (recall that you use the new operator to create a new object): xmldoc = new ActiveXObject("Microsoft.XMLDOM"). Here's how it looks in code:
<HTML> <HEAD> <TITLE> Reading XML element values </TITLE> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc xmldoc = new ActiveXObject("Microsoft.XMLDOM") . . . </HEAD> </HTML>
Now I can load in the XML document meetings.xml:
<HTML> <HEAD> <TITLE> Reading XML element values </TITLE> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc xmldoc = new ActiveXObject("Microsoft.XMLDOM") xmldoc.load("meetings.xml") . . . </HEAD> </HTML>
The next step is to get a node object corresponding to the document's root element, <MEETINGS>. You do that with the documentElement method:
<HTML> <HEAD> <TITLE> Reading XML element values </TITLE> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc, meetingsNode xmldoc = new ActiveXObject("Microsoft.XMLDOM") xmldoc.load("meetings.xml") meetingsNode = xmldoc.documentElement . . . </HEAD> </HTML>
At this point, I'm free to move around the document as I like, using methods such as firstChild, nextChild, previousChild, and lastChild, which let you access the child elements of an element, and the firstSibling, nextSibling, previousSibling, and lastSibling methods, which let you access elements on the same nesting level. For example, the <MEETING> element is the first child of the document root element, <MEETINGS>, so I can get a node corresponding to the <MEETING> element using the firstChild method:
<HTML> <HEAD> <TITLE> Reading XML element values </TITLE> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc, meetingsNode, meetingNode, xmldoc = new ActiveXObject("Microsoft.XMLDOM") xmldoc.load("meetings.xml") meetingsNode = xmldoc.documentElement meetingNode = meetingsNode.firstChild . . . </HEAD> </HTML>
I want to track down the third <PERSON> element inside the <PEOPLE> element. The <PEOPLE> element is the last child of the <MEETING> element, so I can get a node corresponding to the <PEOPLE> element this way:
<HTML> <HEAD> <TITLE> Reading XML element values </TITLE> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc, meetingsNode, meetingNode, peopleNode var first_nameNode, last_nameNode xmldoc = new ActiveXObject("Microsoft.XMLDOM") xmldoc.load("meetings.xml") meetingsNode = xmldoc.documentElement meetingNode = meetingsNode.firstChild peopleNode = meetingNode.lastChild . . . </HEAD> </HTML>
I want the third person in the <PEOPLE> element, which is the last child of this element, so I get access to that person with the lastChild method:
<HTML> <HEAD> <TITLE> Reading XML element values </TITLE> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc, meetingsNode, meetingNode, peopleNode xmldoc = new ActiveXObject("Microsoft.XMLDOM") xmldoc.load("meetings.xml") meetingsNode = xmldoc.documentElement meetingNode = meetingsNode.firstChild peopleNode = meetingNode.lastChild personNode = peopleNode.lastChild . . . </HEAD> </HTML>
Finally, I can get a node corresponding to the <FIRST_NAME> and <LAST_NAME> elements that holds the appropriate person's name using the firstChild and nextSibling (which gets the current node's next sibling node) methods:
<HTML> <HEAD> <TITLE> Reading XML element values </TITLE> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc, meetingsNode, meetingNode, peopleNode var first_nameNode, last_nameNode xmldoc = new ActiveXObject("Microsoft.XMLDOM") xmldoc.load("meetings.xml") meetingsNode = xmldoc.documentElement meetingNode = meetingsNode.firstChild peopleNode = meetingNode.lastChild personNode = peopleNode.lastChild first_nameNode = personNode.firstChild last_nameNode = first_nameNode.nextSibling . . . </HEAD> </HTML>
Now I've walked the tree to get nodes corresponding to the actual elements that I want. Note, however, that the node I want is actually the text nodes inside the <FIRST_NAME> and <LAST_NAME> elements, which hold the person's name. That means that I have to get the first child of those elements (that is, the text node), and then use the nodeValue property of that text node to read the person's name.
To actually display the person's first and last names, I'll use a little dynamic HTML—here, I'm going to use an HTML <DIV> element and the innerHTML property of that element (which holds the text content of the <DIV> element) to display the person's name, like this:
<HTML> <HEAD> <TITLE> Reading XML element values </TITLE> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc, meetingsNode, meetingNode, peopleNode var first_nameNode, last_nameNode, outputText xmldoc = new ActiveXObject("Microsoft.XMLDOM") xmldoc.load("meetings.xml") meetingsNode = xmldoc.documentElement meetingNode = meetingsNode.firstChild peopleNode = meetingNode.lastChild personNode = peopleNode.lastChild first_nameNode = personNode.firstChild last_nameNode = first_nameNode.nextSibling outputText = "Third name: " + first_nameNode.firstChild.nodeValue + ' ' + last_nameNode.firstChild.nodeValue messageDIV.innerHTML=outputText } </SCRIPT> </HEAD> <BODY> <CENTER> <H1> Reading XML element values </H1> <INPUT TYPE="BUTTON" VALUE="Get the name of the third person" ONCLICK="readXMLDocument()"> <P> <DIV ID="messageDIV"></DIV> </CENTER> </BODY> </HTML>
I've also added a button with the caption Get the name of the third person that will call the JavaScript function we've defined, readXMLDocument, and that function reads and displays the document.
You can see this page at work in Internet Explorer in Figure 7.2. When the user clicks the button, the XML document meetings.xml is read and parsed, and we retrieve and display the third person's name. We've made substantial progress.
As of Internet Explorer version 5, you can also use XML data islands to actually embed XML inside HTML pages. Internet Explorer supports an HTML <XML> element (which is not part of the HTML standard) that you can simply enclose an XML document inside, like this:
<XML ID="greeting"> <DOCUMENT> <GREETING>Hi there XML!</GREETING> </DOCUMENT> </XML>
The Internet Explorer <XML> element has some attributes worth noting:
When you use this element, you access it using its ID value in code. To reach the element, you can use the all collection, passing it the ID that you gave the element, like this, for the above example: document.all("greeting"). To get the document object corresponding to the XML document, you can then use the XMLDocument property. Here's how I convert the previous example to use a data island instead of the Microsoft.XMLDOM object:
<HTML> <HEAD> <TITLE> Reading element values with XML data islands </TITLE> <XML ID="meetingsXML" SRC="meetings.xml"></XML> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc, meetingsNode, meetingNode, peopleNode var first_nameNode, last_nameNode, outputText xmldoc= document.all("meetingsXML").XMLDocument meetingsNode = xmldoc.documentElement meetingNode = meetingsNode.firstChild peopleNode = meetingNode.lastChild personNode = peopleNode.lastChild first_nameNode = personNode.firstChild last_nameNode = first_nameNode.nextSibling outputText = "Third name: " + first_nameNode.firstChild.nodeValue + ' ' + last_nameNode.firstChild.nodeValue messageDIV.innerHTML=outputText } </SCRIPT> </HEAD> <BODY> <CENTER> <H1> Reading element values with XML data islands </H1> <INPUT TYPE="BUTTON" VALUE="Get the name of the third person" ONCLICK="readXMLDocument()"> <P> <DIV ID="messageDIV"></DIV> </CENTER> </BODY> </HTML>
This example works as the previous example did, as shown in Figure 7.3.
In the previous example, I used an external XML document, meetings.xml, which I referenced with the <XML> element's SRC attribute. However, you can also enclose the entire XML document in the <XML> element, like this:
<HTML> <HEAD> <TITLE> Creating An XML Data Island </TITLE> <XML ID="meetingsXML"> <?xml version="1.0"?> <MEETINGS> <MEETING TYPE="informal"> <MEETING_TITLE>XML In The Real World</MEETING_TITLE> <MEETING_NUMBER>2079</MEETING_NUMBER> <SUBJECT>XML</SUBJECT> <DATE>6/1/2002</DATE> <PEOPLE> <PERSON ATTENDANCE="present"> <FIRST_NAME>Edward</FIRST_NAME> <LAST_NAME>Samson</LAST_NAME> </PERSON> <PERSON ATTENDANCE="absent"> <FIRST_NAME>Ernestine</FIRST_NAME> <LAST_NAME>Johnson</LAST_NAME> </PERSON> <PERSON ATTENDANCE="present"> <FIRST_NAME>Betty</FIRST_NAME> <LAST_NAME>Richardson</LAST_NAME> </PERSON> </PEOPLE> </MEETING> </MEETINGS> </XML> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc, meetingsNode, meetingNode, peopleNode var first_nameNode, last_nameNode, outputText xmldoc= document.all("meetingsXML").XMLDocument meetingsNode = xmldoc.documentElement meetingNode = meetingsNode.firstChild peopleNode = meetingNode.lastChild personNode = peopleNode.lastChild first_nameNode = personNode.firstChild last_nameNode = first_nameNode.nextSibling outputText = "Third name: " + first_nameNode.firstChild.nodeValue + ' ' + last_nameNode.firstChild.nodeValue messageDIV.innerHTML=outputText } </SCRIPT> </HEAD> <BODY> <CENTER> <H1> Reading element values with XML data islands </H1> <INPUT TYPE="BUTTON" VALUE="Get the name of the third person" ONCLICK="readXMLDocument()"> <P> <DIV ID="messageDIV"></DIV> </CENTER> </BODY> </HTML>
So far, I've used the XMLDocument property of the object corresponding to the XML data island to get the document object, but you can also use the documentElement property of the data island directly to get the root element of the XML document, like this:
<HTML> <HEAD> <TITLE> Reading XML element values </TITLE> <XML ID="meetingsXML" SRC="meetings.xml"></XML> <SCRIPT LANGUAGE="JavaScript"> function readXMLDocument() { var xmldoc, meetingsNode, meetingNode, peopleNode var first_nameNode, last_nameNode, outputText meetingsNode = meetingsXML.documentElement meetingNode = meetingsNode.firstChild peopleNode = meetingNode.lastChild personNode = peopleNode.lastChild first_nameNode = personNode.firstChild last_nameNode = first_nameNode.nextSibling . . . </HTML>