Creating XML Documents with Schemas
“Writing DTDs isn’t easy,” says the novice programmer. “I’ve heard that you can use Microsoft schemas to do the same thing. How does that work?” “Some people don’t find schemas that much easier,” you say, “but pull up a chair and let’s take a look.” The NP rushes off to get coffee.
As we saw in the “In Depth” section of this chapter, XML schemas are Microsoft’s alternative to DTDs. If you want to create valid XML documents for use with Internet Explorer, you can use either a DTD or a schema.
TIP: For Microsoft XML references and information on how to create schemas, see http://msdn.microsoft.com/workshop/xml/index.asp.
Here’s the example I presented in the “In Depth” section of this chapter. This XML document uses a schema named schema1.xml:
<?xml version="1.0" ?>
<TASKFORCE xmlns="x-schema:schema1.xml">
<EMPLOYEE>George Patton</EMPLOYEE>
<EMPLOYEE>Douglas MacArthur</EMPLOYEE>
<DESCRIPTION>XML Programming Taskforce</DESCRIPTION>
</TASKFORCE>
And here’s the schema, schema1.xml, we also developed in the “In Depth” section:
<SCHEMA NAME="schema1"
xmlns="urn:schemas-microsoft-com:xml-data"
xmlns:dt="urn:schemas-microsoft-com:datatypes">
<ELEMENTTYPE name="EMPLOYEE" content="textOnly" model="closed"/>
<ELEMENTTYPE name="DESCRIPTION" content="textOnly" model="closed"/>
<ELEMENTTYPE name="TASKFORCE" content="eltOnly" model="closed">
<ELEMENT type="EMPLOYEE" minOccurs="1" maxOccurs="*"/>
<ELEMENT type="DESCRIPTION" minOccurs="1" maxOccurs="1"/>
</ELEMENTTYPE>
</SCHEMA>
Schemas can get vastly more complex than this, of course. For example, you can use the dt:type attribute to specify the data type of elements (assuming that you create a namespace named dt for Microsoft’s XML data types, as I have in the immediately preceding code). Here’s an example in which I’m specifying that an element can hold integer content:
<ElementType name="count" dt:type="int"/>
You can also use the <datatype> element to do the same thing explicitly:
<ElementType name="count">
<datatype dt:type= "int"/>
</ElementType>
The following list contains the possible data types:
• bin.base64—Multipurpose Internet Mail Extension (MIME)-style Base64 encoded binary object.
• bin.hex—Hexadecimal digits.
• boolean—0 or 1; 0 means false and 1 means true.
• char—String; one character long.
• date—Date with a subset ISO 8601 format that does not contain time data. For example: “2001-09-02”.
• dateTime—Date with a subset ISO 8601 format that contains optional time data but not optional zone data. Fractional seconds can be as exact as nanoseconds. For example, “2001-04-07T22:00:07”.
• dateTime.tz—Date with a subset ISO 8601 format that contains both optional time and optional zone data. Fractional seconds can be as precise as nanoseconds. For example: “2001-04-07T22:00:07-08:00”.
• fixed.14.4—Same as “number” except that there can be no more than 14 digits to the left of the decimal point and no more than 4 to the right.
• float—Real number with no digit limitation; can have leading sign, fractional digits, and optionally, exponent. Values range from 1.7976931348623157E+308 through 2.2250738585072014E-308.
• int—Integer with optional sign but without fractions or exponent.
• number—Number with no digit limitation; potentially can have leading sign, fractional digits, and optionally, exponent. Precision has a range of 1.7976931348623157E+308 through 2.2250738585072014E-308.
• time—Time with a subset ISO 8601 format that does not contain date or time zone. For example: “09:03:54”.
• time.tz—Time with a subset ISO 8601 format that does not contain date but does contain optional time zone. For example: “09:03:54-07:00”.
• i1—Integer denoted in one byte. A number with optional sign but without fractions or exponent. For example: “7, 119, -123”.
• i2—Integer denoted in one word. A number with optional sign but without fractions or exponent. For example: “7, 225, -32000”.
• i4—Integer denoted in four bytes. A number with optional sign but without fractions or exponent. For example: “1, -32000, 278911”.
• r4—Real number having seven-digit precision; can contain leading sign, fractional digits, and optionally, exponent. Values range from 3.40282347E+38F through 1.17549435E-38F.
• r8—Real number having 15-digit precision; potentially can contain leading sign, fractional digits, and optionally, exponent. Values range from 1.7976931348623157E+308 through 2.2250738585072014E-308.
• ui1—Unsigned integer. A number, unsigned, with no fractions or exponent. For example: “231, 6”.
• ui2—Unsigned integer, two bytes. A number, unsigned, with no fractions or exponent. For example: “18, 211, 56789”.
• ui4—Unsigned integer, four bytes. A number, unsigned, no with fractions or exponent. For example: “5, 209, 1234500000”.
• uri—Universal Resource Identifier (URI).
• uuid—Hexadecimal digits denoting octets; optional embedded hyphens are ignored. For example: “195D6A3F-358B4E1D-A439-553A351AAC91”.
For more information on schemas, look at the Microsoft XML site.
Accessing XML Data by Loading XML Documents
“Hm,” says the novice programmer, “now I can create an XML document, and even view it in Internet Explorer. But how can I, um, access the data in it?” You smile and say, “There are two ways—you create an ActiveX object and load an XML page into it, or you can create a data island.” “Let’s see the first way first,” says the NP.
To load an XML document into Internet Explorer, you can use the Microsoft.XMLDOM object to create an ActiveX object, and then use the load method to load the XML document. After the document is loaded, you can use the ActiveX object’s documentElement property to reach the root element of the XML document. After you have the root element, you can navigate around the XML document by using the firstChild, nextChild, previousChild, and lastChild methods, 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 level.
Let’s look at an example, from the “In Depth” section of this chapter, using the XML document, school.xml:
<?xml version="1.0"?>
<SCHOOL>
<CLASS type="seminar">
<CLASS_TITLE>XML In Theory And Practice</CLASS_TITLE>
<CLASS_NUMBER>10.306</CLASS_NUMBER>
<SUBJECT>XML</SUBJECT>
<START_DATE>1/1/2001</START_DATE>
<STUDENTS>
<STUDENT status="attending">
<FIRST_NAME>Mark</FIRST_NAME>
<LAST_NAME>Swansburg</LAST_NAME>
</STUDENT>
<STUDENT status="withdrawn">
<FIRST_NAME>Thomas</FIRST_NAME>
<LAST_NAME>Preston</LAST_NAME>
</STUDENT>
</STUDENTS>
</CLASS>
</SCHOOL>
The Web page I developed in the “In Depth” section of this chapter read in this XML document and, by using the navigation methods already discussed, moved to the second student’s record. To access the data in that record, I use the nodeValue property:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Finding Element Values in an XML Document
</title>
<script type="text/javascript" language="javascript">
function getStudentData()
{
var xmldoc;
xmldoc = new ActiveXObject("Microsoft.XMLDOM");
xmldoc.load("school.xml");
nodeSchool = xmldoc.documentElement;
nodeClass = nodeSchool.firstChild;
nodeStudents = nodeClass.lastChild;
nodeStudent = nodeStudents.lastChild;
nodeFirstName = nodeStudent.firstChild;
nodeLastName = nodeFirstName.nextSibling;
outputMessage = "Name: " +
nodeFirstName.firstChild.nodeValue + ' '
+ nodeLastName.firstChild.nodeValue;
message.innerHTML=outputMessage;
}
</script>
</head>
<body>
<center>
<h1>
Finding Element Values in an XML Document
</h1>
<div id="message"></div>
<p>
<input type="button" value="Get Second Student's Name"
onclick="getStudentData()" />
</p>
</center>
</body>
</html>
You can see the results of this HTML and XML in Figure 15.2. Loading an XML document with the load method is one way of accessing it; the other is to use data islands.
<xml>—Accessing XML Data with an XML Data Island
Purpose: Creates an XML data island in Internet Explorer and embeds an XML document in a Web page.
When used as HTML: Start tag/End tag: Required/Required
Supported: [IE5]
Attributes:
• disabled—Indicates whether the element is disabled. [IE5]
• id—Unique alphanumeric identifier for the tag; use the ID to refer to the
tag. [IE5]
• src—Specifies the source for the XML document. Set to a URL. [IE5]
XHTML events: None
“Hm,” says the novice programmer, “loading in an XML element is OK, but didn’t you say something about data islands?” “Yes,” you say, “I sure did. You create data islands with the <xml> element, and you can mix XHTML and XML in this way.”
You use Internet Explorer’s HTML <xml> element to enclose XML data in a Web page, creating a data island. Here’s an example in which I’m embedding school.xml, an XML document that contains student records, in a data island (note that since the <xml> element is specific to Internet Explorer, this example is not strictly conforming XHTML):
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Creating An XML Data Island
</title>
<xml id="schoolXML">
<SCHOOL>
<CLASS type="seminar">
<CLASS_TITLE>XML In Theory And Practice</CLASS_TITLE>
<CLASS_NUMBER>10.306</CLASS_NUMBER>
<SUBJECT>XML</SUBJECT>
<START_DATE>1/1/2001</START_DATE>
<STUDENTS>
<STUDENT status="attending">
<FIRST_NAME>Mark</FIRST_NAME>
<LAST_NAME>Swansburg</LAST_NAME>
</STUDENT>
<STUDENT status="withdrawn">
<FIRST_NAME>Thomas</FIRST_NAME>
<LAST_NAME>Preston</LAST_NAME>
</STUDENT>
</STUDENTS>
</CLASS>
</SCHOOL>
</xml>
</head>
<body>
<center>
<h1>
Creating An XML Data Island
</h1>
</center>
</body>
</html>
You don’t need to embed the whole XML document in the data island, however; you can simply use the src attribute to point to the XML document:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Creating An XML Data Island
</title>
<xml id="schoolXML" src="school.xml"></xml>
</head>
<body>
<center>
<h1>
Creating An XML Data Island
</h1>
</center>
</body>
</html>
Here’s the file school.xml:
<?xml version="1.0"?>
<SCHOOL>
<CLASS type="seminar">
<CLASS_TITLE>XML In Theory And Practice</CLASS_TITLE>
<CLASS_NUMBER>10.306</CLASS_NUMBER>
<SUBJECT>XML</SUBJECT>
<START_DATE>1/1/2001</START_DATE>
<STUDENTS>
<STUDENT status="attending">
<FIRST_NAME>Mark</FIRST_NAME>
<LAST_NAME>Swansburg</LAST_NAME>
</STUDENT>
<STUDENT status="withdrawn">
<FIRST_NAME>Thomas</FIRST_NAME>
<LAST_NAME>Preston</LAST_NAME>
</STUDENT>
</STUDENTS>
</CLASS>
</SCHOOL>
In an example from the “In Depth” section of this chapter, I demonstrated how to use the navigation methods to get to the second student’s record and display that student’s name. You navigate around the XML document by using the firstChild, nextChild, previousChild, and lastChild methods, 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 level. To get the content of an element, I use the nodeValue property. Here’s the JavaScript that we developed:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Finding Element Values in an XML Document Using Data Islands
</title>
<xml id="schoolXML" src="school.xml"></xml>
<script type="text/javascript" language="javascript">
function getStudentData()
{
xmldoc= document.all("schoolXML").XMLDocument;
nodeSchool = xmldoc.documentElement;
nodeClass = nodeSchool.firstChild;
nodeStudents = nodeClass.lastChild;
nodeStudent = nodeStudents.lastChild;
nodeFirstName = nodeStudent.firstChild;
nodeLastName = nodeFirstName.nextSibling;
outputMessage = "Name: " +
nodeFirstName.firstChild.nodeValue + ' '
+ nodeLastName.firstChild.nodeValue;
message.innerHTML=outputMessage;
}
</script>
</head>
<body>
<center>
<h1>
Finding Element Values in an XML Document Using
Data Islands
</h1>
<div id="message"></div>
<p>
<input type="button" value="Get Second Student's Name"
onclick="getStudentData()" />
</center>
</body>
</html>
You can see the results in Figure 15.3.
In this case, I used the XMLDocument property to get an object corresponding to the HTML document, and then used the documentElement property of that object to get the root element of the document. However, there’s a shortcut for this process. You can simply use the documentElement property of the data island to get the root element of the XML document:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Finding Element Values in an XML Document
</title>
<xml id="schoolXML" src="school.xml"></xml>
<script type="text/javascript" language="javascript">
function getStudentData()
{
var xmldoc;
nodeSchool = schoolXML.documentElement;
nodeClass = nodeSchool.firstChild;
nodeStudents = nodeClass.lastChild;
nodeStudent = nodeStudents.lastChild;
nodeFirstName = nodeStudent.firstChild;
nodeLastName = nodeFirstName.nextSibling;
.
.
.
</html>
Note that these examples extract the values of XML elements from an XML document, but not their attributes. To extract attribute values as well, see the next section.
Getting Attribute Values from XML Elements
“One problem,” says the novice programmer. “I know I can use the nodeValue property to get the content of XML elements, but what about getting the values of attributes?” “No problem,” you say; “just use the attributes property.”
Say that you have an XML document named school.xml, in which the <STUDENT> element has one attribute, STATUS:
<?xml version="1.0"?>
<SCHOOL>
<CLASS type="seminar">
<CLASS_TITLE>XML In Theory And Practice</CLASS_TITLE>
<CLASS_NUMBER>10.306</CLASS_NUMBER>
<SUBJECT>XML</SUBJECT>
<START_DATE>1/1/2001</START_DATE>
<STUDENTS>
<STUDENT status="attending">
<FIRST_NAME>Mark</FIRST_NAME>
<LAST_NAME>Swansburg</LAST_NAME>
</STUDENT>
<STUDENT status="withdrawn">
<FIRST_NAME>Thomas</FIRST_NAME>
<LAST_NAME>Preston</LAST_NAME>
</STUDENT>
</STUDENTS>
</CLASS>
</SCHOOL>
How can you recover these attribute values? Here’s an example showing how it’s done. In this case, I’m reading the value of the status attribute of the second student’s record. I use the attributes property to get that record’s attributes. Then I use the getNamedItem method to get the value of the status attribute, like this: statusStudent = attributes.getNamedItem("status");. I then use statusStudent.value to get the text that the attribute was set to. Here’s what the JavaScript looks like:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Finding Attribute Values in an XML Document
</title>
<xml id="schoolXML" src="school.xml"></xml>
<script type="text/javascript" language="javascript">
function getStudentData()
{
xmldoc= document.all("schoolXML").XMLDocument;
nodeSchool = xmldoc.documentElement;
nodeClass = nodeSchool.firstChild;
nodeStudents = nodeClass.lastChild;
nodeStudent = nodeStudents.lastChild;
nodeFirstName = nodeStudent.firstChild;
nodeLastName = nodeFirstName.nextSibling;
attributes = nodeStudent.attributes;
statusStudent = attributes.getNamedItem("status");
outputMessage = "Name: " +
nodeFirstName.firstChild.nodeValue + ' '
+ nodeLastName.firstChild.nodeValue + " Status: " +
statusStudent.value;
message.innerHTML=outputMessage;
}
</script>
</head>
<body>
<center>
<h1>
Finding Attribute Values in an XML Document
</h1>
<div id="message"></div>
<p>
<input type="button" value="Get Second Student's Status"
onclick="getStudentData()" />
</p>
</center>
</body>
</html>
And that’s all it takes. In Figure 15.4, you see that the status of the second student is "withdrawn".
Figure 15.4 Accessing attribute values in an XML document.
Parsing XML Documents in Code
So far in this chapter I’ve used navigation methods such as nextSibling and nextChild to navigate through XML documents. However, I knew just what element I was after and wrote the code accordingly. Usually (that is, when you don’t know the exact contents of the files the user is asking you to read), you should parse XML documents, working through the entire document and unpacking the data in it.
One way of parsing an XML document is to use the childNodes property, which tells you whether an element has any children. In this example, I’ll work through the entire XML document, school.xml, displaying all its elements in an XHTML Web page:
<?xml version="1.0"?>
<SCHOOL>
<CLASS type="seminar">
<CLASS_TITLE>XML In Theory And Practice</CLASS_TITLE>
<CLASS_NUMBER>10.306</CLASS_NUMBER>
<SUBJECT>XML</SUBJECT>
<START_DATE>1/1/2001</START_DATE>
<STUDENTS>
<STUDENT status="attending">
<FIRST_NAME>Mark</FIRST_NAME>
<LAST_NAME>Swansburg</LAST_NAME>
</STUDENT>
<STUDENT status="withdrawn">
<FIRST_NAME>Thomas</FIRST_NAME>
<LAST_NAME>Preston</LAST_NAME>
</STUDENT>
</STUDENTS>
</CLASS>
</SCHOOL>
I’ll create a function, getChildren, which gets and displays the children of an element. (This is a recursive function, which means that it can call itself to get the children of an element’s children, and so on to many levels in depth). To display the current element’s name, I use the nodeName property. To start parsing the whole page then, I just have to call getChildren on the root node of the whole document. I do that in a function named parseXML, which I connect to a button in this Web page:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Parsing an XML Document with Recursion
</title>
<xml id="schoolXML" src="school.xml"></xml>
<script type="text/javascript" language="javascript"
src="script.js">
</script>
</head>
<body>
<center>
<h1>
Parsing an XML Document
</h1>
</center>
<div id="divResults"></div>
<center>
<input type="button" value="Parse the XML Document"
onclick="parseXML()" />
</center>
</body>
</html>
Here’s the script used by this page, script.js:
function parseXML()
{
documentXML = document.all("schoolXML").XMLDocument;
divResults.innerHTML = getChildren(documentXML, "");
}
function getChildren(nodeXML, indent)
{
var text = indent + nodeXML.nodeName + "<br />";
if (nodeXML.childNodes.length > 0) {
for (var loopIndex = 0; loopIndex <
nodeXML.childNodes.length; loopIndex++) {
text += getChildren(nodeXML.childNodes(loopIndex),
indent + " ");
}
}
return text;
}
When you click the button in this page, it will read school.xml and display its structure, as you see in Figure 15.5. In this way, you can loop over every element in an XML document. There’s one detail to note—Internet Explorer considers more than just elements in the document to be nodes; processing instructions, the text content of elements, the root element, and more are all nodes (see the next section for more information). Usually, you’ll just look for specific elements and want to read their data content—the next section discusses how to do this.
Figure 15.5 Parsing an XML document.
Parsing XML to Get Element Content
In the previous section, we saw how to parse an entire XML document, school.xml, by “walking” through it recursively. However, that example just listed the structure of the XML document. Here, I’ll elaborate on that code by also displaying each node’s type and content. I do that by checking the nodeType property to get the node’s type and checking the nodeValue property to get the node’s value. In this example, note the different types of items that Internet Explorer considers to be nodes in XML documents: processing instructions, the text content of an element, comments, and even the document (root) element itself. Here’s the new code:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Parsing an XML Document To Get Element Content
</title>
<xml id="schoolXML" src="school.xml"></xml>
<script type="text/javascript" language="javascript"
src="script.js">
</script>
</head>
<body>
<center>
<h1>
Parsing an XML Document To Get Element Content
</h1>
</center>
<div id="divResults"></div>
<center>
<input type="button" value="Parse the XML Document"
onclick="parseXML()" />
</center>
</body>
</html>
Here’s the script, script.js, used by this page:
function parseXML()
{
documentXML = document.all("schoolXML").XMLDocument;
divResults.innerHTML = getChildren(documentXML, "");
}
function getChildren(nodeXML, indent)
{
var typeXML;
switch (nodeXML.nodeType) {
case 1:
typeXML = "element";
break;
case 2:
typeXML = "attribute";
break;
case 3:
typeXML = "text";
break;
case 4:
typeXML = "CDATA section";
break;
case 5:
typeXML = "entity reference";
break;
case 6:
typeXML = "entity";
break;
case 7:
typeXML = "processing instruction";
break;
case 8:
typeXML = "comment";
break;
case 9:
typeXML = "document";
break;
case 10:
typeXML = "document type";
break;
case 11:
typeXML = "document fragment";
break;
case 12:
typeXML = "notation";
}
var text = indent + nodeXML.nodeName
+ (nodeXML.nodeValue ?
" = " + nodeXML.nodeValue
+ " (Type: " + typeXML
+ ")<br />" :
" (Type: " + typeXML
+ ")<br />");
if (nodeXML.childNodes.length > 0) {
for (var loopIndex = 0; loopIndex <
nodeXML.childNodes.length; loopIndex++) {
text += getChildren(nodeXML.childNodes(loopIndex),
indent + " ");
}
}
return text;
}
You can see the results of this HTML and XML in Figure 15.6. The code displays not only the type of each node but also the content if the node is a text node.
Figure 15.6 Parsing an XML document to get element content.
Some of the elements in school.xml have attributes—so how can we list them, too? See the next section.
Parsing XML to Get Attribute Values
In the previous two sections, we developed JavaScript code to display the full structure of an XML document, school.xml, and to display its node types and data. But so far we haven’t displayed any attribute values, even though some of the elements in school.xml have attributes:
<SCHOOL>
<CLASS_TITLE>XML In Theory And Practice</CLASS_TITLE>
<CLASS_NUMBER>10.306</CLASS_NUMBER>
<SUBJECT>XML</SUBJECT>
<START_DATE>1/1/2001</START_DATE>
<STUDENTS>
<STUDENT status="attending">
<FIRST_NAME>Mark</FIRST_NAME>
<LAST_NAME>Swansburg</LAST_NAME>
</STUDENT>
<STUDENT status="withdrawn">
<FIRST_NAME>Thomas</FIRST_NAME>
<LAST_NAME>Preston</LAST_NAME>
</STUDENT>
</STUDENTS>
</CLASS>
</SCHOOL>
To access the attributes of a node, all I have to do is use the attributes property to get access to the attributes object. To get the name of the attribute, I can use the nodeName property, and to get the attribute’s value, I can use the nodeValue property. (Internet Explorer considers attributes to be nodes.) All that’s left is to loop over all the attributes an element has, and I can determine the number of attributes to loop over by checking the attributes object’s length property. Here is how I list all the attributes of an XML element:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Parsing an XML Document To Get Element And Attribute Content
</title>
<xml id="schoolXML" src="school.xml"></xml>
<script type="text/javascript"
language="javascript" src="script.js">
</script>
</head>
<body>
<center>
<h1>
Parsing an XML Document To Get Element And Attribute Content
</h1>
</center>
<div id="divResults"></div>
<center>
<input type="button" value="Parse the XML Document"
onclick="parseXML()" />
</center>
</body>
</html>
Here’s the script, script.js, used by this page:
function parseXML()
{
documentXML = document.all("schoolXML").XMLDocument;
divResults.innerHTML = getChildren(documentXML, "");
}
function getChildren(nodeXML, indent)
{
var typeXML;
switch (nodeXML.nodeType) {
case 1:
typeXML = "element";
break;
case 2:
typeXML = "attribute";
break;
case 3:
typeXML = "text";
break;
case 4:
typeXML = "CDATA section";
break;
case 5:
typeXML = "entity reference";
break;
case 6:
typeXML = "entity";
break;
case 7:
typeXML = "processing instruction";
break;
case 8:
typeXML = "comment";
break;
case 9:
typeXML = "document";
break;
case 10:
typeXML = "document type";
break;
case 11:
typeXML = "document fragment";
break;
case 12:
typeXML = "notation";
}
var text = indent + nodeXML.nodeName
+ (nodeXML.nodeValue ?
" = " + nodeXML.nodeValue
+ " (Type: " + typeXML
+ ")" :
" (Type: " + typeXML
+ ")");
if (nodeXML.attributes != null) {
if (nodeXML.attributes.length > 0) {
for (var loopIndex = 0; loopIndex <
nodeXML.attributes.length; loopIndex++) {
text += " (Attribute: " +
nodeXML.attributes(loopIndex).nodeName +
" = " +
nodeXML.attributes(loopIndex).nodeValue
+ ")";
}
}
}
text += "<br />";
if (nodeXML.childNodes.length > 0) {
for (var loopIndex = 0; loopIndex <
nodeXML.childNodes.length; loopIndex++) {
text += getChildren(nodeXML.childNodes(loopIndex),
indent + " ");
}
}
return text;
}
The result of this HTML and XML appears in Figure 15.7, where you can see
the names and values of attributes as well as the names and values of the XML elements.
Figure 15.7 Parsing an XML document to get element and attribute content.
Handling Events while Loading XML Documents
“One more question,” the novice programmer says. “My XML document is coming in from the Internet and it takes half an hour to load. How can I make sure the document is fully loaded before I use it?” “No idea,” you say. The NP says, “Huh?” “Just kidding,” you smile and say. “You can use the ondataavailable event.”
You can use the onreadystatechange and ondataavailable events to monitor the progress of loading XML documents. You can also check the readyState property in the onreadystatechange event to determine the status of the document. Here’s an example that monitors and displays the progress of loading an XML document:
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Handling XML Loading Events
</title>
<script type="text/javascript"
language="javascript" src="script.js">
</script>
</head>
<body>
<center>
<h1>
Handling XML Loading Events
</h1>
</center>
<div id="div1"></div>
<center>
<input type="button" value="Load the XML file"
onclick="loadFile()" />
</center>
</body>
</html>
Here’s the script, script.js, used by this page:
var xmldoc;
function loadFile()
{
xmldoc = new ActiveXObject("microsoft.XMLDOM");
xmldoc.onreadystatechange = dataChange;
xmldoc.ondataavailable = dataAvailable;
xmldoc.load('school.xml');
}
function dataChange()
{
switch (xmldoc.readyState)
{
case 1:
div1.innerHTML += "Data is uninitialized.<br />";
break;
case 2:
div1.innerHTML += "Data is loading.<br />";
break;
case 3:
div1.innerHTML += "Data has been loaded.<br />";
break;
case 4:
div1.innerHTML += "Data loading is complete.<br />";
if (xmldoc.parseError.errorCode != 0) {
div1.innerHTML += "An error occurred.<br />";
}
else {
div1.innerHTML += "File loaded OK.<br />";
}
break;
}
}
function dataAvailable()
{
div1.innerHTML += 'Data is available.<br />';
}
You can see the results of this HTML and XML in Figure 15.8, which reports each step of the loading process.
Figure 15.8 Handling XML loading events.
Page 4 of 5. Goto Page 1 | 2 | 3 | 5
|