2002 prentice hall, inc. all rights reserved. chapter 8 – document object model (dom) outline...
TRANSCRIPT
2002 Prentice Hall, Inc. All rights reserved.
Chapter 8 – Document Object Model (DOM)
Outline8.1 Introduction8.2 DOM Implementation8.3 DOM with JavaScript8.4 Setup8.5 DOM Components8.6 Creating Nodes8.7 Traversing the DOM8.8 Case Study: Modify the Day Planner Application to Use the DOM
2002 Prentice Hall, Inc. All rights reserved.
8.1 Introduction
• XML Document Object Model (DOM)– W3C standard recommendation
– Build tree structure in memory for XML documents
– DOM-based parsers parse these structures• Exist in several languages (Java, C, C++, Python, Perl, etc.)
2002 Prentice Hall, Inc. All rights reserved.
8.1 Introduction
• DOM tree– Each node represents an element, attribute, etc.
<?xml version = "1.0"?><message from = "Paul" to = "Tem"> <body>Hi, Tim!</body></message>
• Node created for element message– Element message has child node for body element
– Element body has child node for text "Hi, Tim!"– Attributes from and to also have nodes in tree
2002 Prentice Hall, Inc. All rights reserved.
8.2 DOM Implementations
• DOM-based parsers– Microsoft’s msxml
– Sun Microsystem’s JAXP
2002 Prentice Hall, Inc. All rights reserved.
Fig. 8.1 Some DOM-based parsers. Parser Description
JAXP Sun Microsystem’s Java API for XML Parsing (JAXP) is available at no charge from java.sun.com/xml.
XML4J IBM’s XML Parser for Java (XML4J) is available at no charge from www.alphaworks.ibm.com/tech/xml4j.
Xerces Apache’s Xerces Java Parser is available at no charge from xml.apache.org/xerces.
msxml Microsoft’s XML parser (msxml) version 2.0 is built-into Internet Explorer 5.5. Version 3.0 is also available at no charge from msdn.microsoft.com/xml.
4DOM 4DOM is a parser for the Python programming language and is available at no charge from fourthought.com/4Suite/4DOM.
XML::DOM XML::DOM is a Perl module that we use in Chapter 17 to manipulate XML documents using Perl. For additional information, visit www-4.ibm.com/software/developer/library/xml-perl2.
2002 Prentice Hall, Inc. All rights reserved.
8.3 DOM and JavaScript
• We use JavaScript and msxml parser– XML document marks up article
– Use DOM API to display document’s element names/values
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.2 Article marked up with XML tags.
1 <?xml version = "1.0"?>
2
3 <!-- Fig. 8.2: article.xml -->
4 <!-- Article formatted with XML -->
5
6 <article>
7
8 <title>Simple XML</title>
9
10 <date>December 6, 2000</date>
11
12 <author>
13 <fname>Tem</fname>
14 <lname>Nieto</lname>
15 </author>
16
17 <summary>XML is pretty easy.</summary>
18
19 <content>Once you have mastered HTML, XML is easily
20 learned. You must remember that XML is not for
21 displaying information but for managing information.
22 </content>
23
24 </article>
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.3 Traversing article.xml with JavaScript.
Element script allows for including scripting code
Instantiate Microsoft XML DOM object
Load article.xml into memory; msxml parses article.xml and stores it as tree structure
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
2 "http://www.w3.org/TR/html4/strict.dtd">
3
4 <html>
5
6 <!-- Fig. 8.3 : DOMExample.html -->
7 <!-- DOM with JavaScript -->
8
9 <head>
10 <title>A DOM Example</title>
11 </head>
12
13 <body>
14
15 <script type = "text/javascript" language = "JavaScript">
16
17 var xmlDocument = new ActiveXObject( "Microsoft.XMLDOM" );
18
19 xmlDocument.load( "article.xml" );
20
Element script allows for including scripting code
Instantiate Microsoft XML DOM object
Load article.xml into memory; msxml parses article.xml and
stores it as tree structure
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.3 Traversing article.xml with JavaScript. (Part 2)
Assign article as root element
Place root element’s name in element strong and write it to browser
Assign index to each child node of root node
Retrieve root node’s first child node (title)
21 // get the root element
22 var element = xmlDocument.documentElement;
23
24 document.writeln(
25 "<p>Here is the root node of the document:" );
26 document.writeln( "<strong>" + element.nodeName
27 + "</strong>" );
28
29 document.writeln(
30 "<br>The following are its child elements:" );
31 document.writeln( "</p><ul>" );
32
33 // traverse all child nodes of root element
34 for ( i = 0; i < element.childNodes.length; i++ ) {
35 var curNode = element.childNodes.item( i );
36
37 // print node name of each child element
38 document.writeln( "<li><strong>" + curNode.nodeName
39 + "</strong></li>" );
40 }
41
42 document.writeln( "</ul>" );
43
44 // get the first child node of root element
45 var currentNode = element.firstChild;
46
Assign article as root element
Place root element’s name in element strong and write it to browser
Assign index to each child node of root node
Retrieve root node’s first child node (title)
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.3 Traversing article.xml with JavaScript. (Part 3)
Siblings are nodes at same level in document (e.g., title, date, author, summary and content)
Get first child’s next sibling (date)
Get first child of date (December 6, 2000)
Get parent of date (article)
47 document.writeln( "<p>The first child of root node is:" );
48 document.writeln( "<strong>" + currentNode.nodeName
49 + "</strong>" );
50 document.writeln( "<br>whose next sibling is:" );
51
52 // get the next sibling of first child
53 var nextSib = currentNode.nextSibling;
54
55 document.writeln( "<strong>" + nextSib.nodeName
56 + "</strong>." );
57 document.writeln( "<br>Value of <strong>" + nextSib.nodeName
58 + "</strong> element is:" );
59
60 var value = nextSib.firstChild;
61
62 // print the text value of the sibling
63 document.writeln( "<em>" + value.nodeValue + "</em>" );
64 document.writeln( "<br>Parent node of " );
65 document.writeln( "<string>" + nextSib.nodeName
66 + "</strong> is:" );
67 document.writeln( "<strong>" + nextSib.parentNode.nodeName
68 + "</strong>.</p>" );
69
70 </script>
71
72 </body>
73 </html>
Siblings are nodes at same level in document (e.g., title, date,
author, summary and content)
Get first child’s next sibling (date)
Get first child of date (December 6, 2000)
Get parent of date (article)
2002 Prentice Hall, Inc. All rights reserved.
Fig. 8.3 Traversing article.xml with JavaScript.
2002 Prentice Hall, Inc. All rights reserved.
8.4 Setup
• Java applications to illustrate DOM API– Java 2 Standard Edition required
• Download at www.java.sun.com/j2se• Installation instructions
– www.deitel.com/faq/java3install.htm
– JAXP required• Download at java.sun.com/xml/download.html
2002 Prentice Hall, Inc. All rights reserved.
8.5 DOM Components
• Manipulate XML document– Use Java, JAXP and XML-related Java packages
2002 Prentice Hall, Inc. All rights reserved.
Fig. 8.4 DOM classes and interfaces.
Class/Interface Description
Document interface Represents the XML document’s top-level node, which provides access to all the document’s nodes—including the root element.
Node interface Represents an XML document node.
NodeList interface Represents a read-only list of Node objects.
Element interface Represents an element node. Derives from Node.
Attr interface Represents an attribute node. Derives from Node.
CharacterData interface Represents character data. Derives from Node.
Text interface Represents a text node. Derives from CharacterData.
Comment interface Represents a comment node. Derives from CharacterData.
ProcessingInstruction interface
Represents a processing instruction node. Derives from Node.
CDATASection interface Represents a CDATA section. Derives from Text.
2002 Prentice Hall, Inc. All rights reserved.
Fig. 8.5 Some Document methods.
Method Name Description
createElement Creates an element node.
createAttribute Creates an attribute node.
createTextNode Creates a text node.
createComment Creates a comment node.
createProcessingInstruction Creates a processing instruction node.
createCDATASection Creates a CDATA section node.
getDocumentElement Returns the document’s root element.
appendChild Appends a child node.
getChildNodes Returns the child nodes.
2002 Prentice Hall, Inc. All rights reserved.
Fig. 8.6 XmlDocument methods.
Method Name Description
createXmlDocument Parses an XML document.
write Outputs the XML document.
2002 Prentice Hall, Inc. All rights reserved.
Fig. 8.7 Node methods.
Method Name Description
appendChild Appends a child node.
cloneNode Duplicates the node.
getAttributes Returns the node’s attributes.
getChildNodes Returns the node’s child nodes.
getNodeName Returns the node’s name.
getNodeType Returns the node’s type (e.g., element, attribute, text, etc.). Node types are described in greater detail in Fig. 8.9.
getNodeValue Returns the node’s value.
getParentNode Returns the node’s parent.
hasChildNodes Returns true if the node has child nodes.
removeChild Removes a child node from the node.
replaceChild Replaces a child node with another node.
setNodeValue Sets the node’s value.
insertBefore Appends a child node in front of a child node.
2002 Prentice Hall, Inc. All rights reserved.
Fig. 8.8 Some node types.
Node Type Description
Node.ELEMENT_NODE Represents an element node.
Node.ATTRIBUTE_NODE Represents an attribute node.
Node.TEXT_NODE Represents a text node.
Node.COMMENT_NODE Represents a comment node.
Node.PROCESSING_INSTRUCTION_NODE Represents a processing instruction node.
Node.CDATA_SECTION_NODE Represents a CDATA section node.
2002 Prentice Hall, Inc. All rights reserved.
Fig. 8.9 Element methods.
Method Name Description
getAttribute Returns an attribute’s value.
getTagName Returns an element’s name.
removeAttribute Removes an element’s attribute.
setAttribute Sets an attribute’s value.
2002 Prentice Hall, Inc. All rights reserved.
8.5 DOM Components (cont.)
• Our first Java-based example:– Validates intro.xml– Replaces text in element message with new text
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.10Simple example to replace an existing text node.
import specifies location of classes needed by application
Declare reference to Document object
DocumentBuilder-Factory (parser) will create Document-Builder
Require parser to validate documents
Interface for loading and parsing documents
1 // Fig 8.10 : ReplaceText.java
2 // Reads intro.xml and replaces a text node.
3
4 import java.io.*;
5 import org.w3c.dom.*;
6 import javax.xml.parsers.*;
7 import com.sun.xml.tree.XmlDocument;
8 import org.xml.sax.*;
9
10 public class ReplaceText {
11 private Document document;
12
13 public ReplaceText()
14 {
15 try {
16
17 // obtain the default parser
18 DocumentBuilderFactory factory =
19 DocumentBuilderFactory.newInstance();
20
21 // set the parser to validating
22 factory.setValidating( true );
23
24 DocumentBuilder builder = factory.newDocumentBuilder();
25
import specifies location of classes needed by application
Declare reference to Document object
DocumentBuilderFactory (parser) will create
DocumentBuilder
Require parser to validate documents
Interface for loading and parsing documents
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.10Simple example to replace an existing text node. (Part 2)
Load and parse document (intro.xml)
Get document root node
Test if root node is element
Cast root node as element, then get list of all message elements in document
If message element exists, replace old text node with new one
26 // set error handler for validation errors27 builder.setErrorHandler( new MyErrorHandler() );2829 // obtain document object from XML document30 document = builder.parse( new File( "intro.xml" ) );3132 // fetch the root node33 Node root = document.getDocumentElement();3435 if ( root.getNodeType() == Node.ELEMENT_NODE ) {36 Element myMessageNode = ( Element ) root;37 NodeList messageNodes = 38 myMessageNode.getElementsByTagName( "message" );3940 if ( messageNodes.getLength() != 0 ) {41 Node message = messageNodes.item( 0 );4243 // create a text node44 Text newText = document.createTextNode(45 "New Changed Message!!" );4647 // get the old text node48 Text oldText =49 ( Text ) message.getChildNodes().item( 0 ); 5051 // replace the text 52 message.replaceChild( newText, oldText );53 }54 } 55
Load and parse document (intro.xml)
Get document root node
Test if root node is element
Cast root node as element, then get list of all message
elements in document
If message element exists, replace old text node with new one
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.10Simple example to replace an existing text node. (Part 3)
Write new XML document to intro1.xml
Handles errors that may have occurred
Method main starts application
Output for Fig. 8.10
56 ( (XmlDocument) document).write( new FileOutputStream(57 "intro1.xml" ) ); 58 } 59 catch ( SAXParseException spe ) {60 System.err.println( "Parse error: " + 61 spe.getMessage() );62 System.exit( 1 );63 }64 catch ( SAXException se ) {65 se.printStackTrace(); 66 }67 catch ( FileNotFoundException fne ) {68 System.err.println( "File \'intro.xml\' not found. " );69 System.exit( 1 );70 }71 catch ( Exception e ) {72 e.printStackTrace();73 }74 }75 76 public static void main( String args[] )77 {78 ReplaceText d = new ReplaceText(); 79 }80 }
Write new XML document to intro1.xml
Handles errors that may have occurred
Method main starts application
set PATH=%PATH%;C:\jdk1.3\bin\set CLASSPATH=%CLASSPATH%;C:\jaxp\jaxp.jar;C:\jaxp\parser.jar;.javac ReplaceText.java MyErrorHandler.javajava ReplaceText
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.11Class definition for MyErrorHandler.
ReplaceText (Fig.8.10) instantiates MyErrorHandler to throw exceptions upon errors
1 // Fig 8.11 : MyErrorHandler.java2 // Error Handler for validation errors.34 import org.xml.sax.ErrorHandler;5 import org.xml.sax.SAXException;6 import org.xml.sax.SAXParseException;78 public class MyErrorHandler implements ErrorHandler 9 {1011 // throw SAXException for fatal errors12 public void fatalError( SAXParseException exception )13 throws SAXException 14 {15 throw exception;16 }1718 public void error( SAXParseException e )19 throws SAXParseException20 {21 throw e;22 }2324 // print any warnings 25 public void warning( SAXParseException err )26 throws SAXParseException27 {28 System.err.println( "Warning: " + err.getMessage() );29 }30 }
ReplaceText (Fig.8.10) instantiates MyErrorHandler to throw exceptions upon errors
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.12Input document (intro.xml).
XML document manipulated by ReplaceText Java applciation
1 <?xml version = "1.0"?>
2
3 <!-- Fig. 8.12 : intro.xml -->
4 <!-- Simple introduction to XML markup -->
5
6 <!DOCTYPE myMessage [
7 <!ELEMENT myMessage ( message )>
8 <!ELEMENT message ( #PCDATA )>
9 ]>
10
11 <myMessage>
12 <message>Welcome to XML!</message>
13 </myMessage>
XML document manipulated by ReplaceText Java applciation
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.13Ouput of replaceText.java, which is stored in intro1.xml.
ReplaceText application creates this XML document
1 <?xml version = "1.0" encoding = "UTF-8"?>
2
3 <!-- Fig. 8.12 : intro.xml -->
4 <!-- Simple introduction to XML markup -->
5
6 <!DOCTYPE myMessage [
7 <!ELEMENT myMessage ( message )>
8 <!ELEMENT message ( #PCDATA )>
9 ]>
10
11 <myMessage>
12 <message>New Changed Message!!</message>
13 </myMessage>
ReplaceText application creates this XML document
2002 Prentice Hall, Inc. All rights reserved.
8.6 Creating Nodes
• Create XML document at run time– BuildXML Java application
• creates document for contact list
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.14Building an XML document with the DOM.
Use JAXP default parser
DocumentBuilder loads and parses XML documents
1 // Fig. 8.14 : BuildXml.java
2 // Creates element node, attribute node, comment node,
3 // processing instruction and a CDATA section.
4
5 import java.io.*;
6 import org.w3c.dom.*;
7 import org.xml.sax.*;
8 import javax.xml.parsers.*;
9 import com.sun.xml.tree.XmlDocument;
10
11 public class BuildXml {
12 private Document document;
13
14 public BuildXml()
15 {
16
17 DocumentBuilderFactory factory =
18 DocumentBuilderFactory.newInstance();
19
20 try {
21
22 // get DocumentBuilder
23 DocumentBuilder builder =
24 factory.newDocumentBuilder();
25
Use JAXP default parser
DocumentBuilder loads and parses XML documents
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.14Building an XML document with the DOM. (Part 2)
Obtain XML Document reference
Create root Element and append to Document
Create Comment node and append to root node
Call method createContactNode (next slide) to create child node
Create Processing-Instruction node with target myInstruction and value action silent
26 // create root node
27 document = builder.newDocument();
28 }
29 catch ( ParserConfigurationException pce ) {
30 pce.printStackTrace();
31 }
32
33 Element root = document.createElement( "root" );
34 document.appendChild( root );
35
36 // add a comment to XML document
37 Comment simpleComment = document.createComment(
38 "This is a simple contact list" );
39 root.appendChild( simpleComment );
40
41 // add a child element
42 Node contactNode = createContactNode( document );
43 root.appendChild( contactNode );
44
45 // add a processing instruction
46 ProcessingInstruction pi =
47 document.createProcessingInstruction(
48 "myInstruction", "action silent" );
49 root.appendChild( pi );
50
Obtain XML Document
reference
Create root Element and append to Document
Create Comment node and append to root node
Call method createContactNode (next
slide) to create child node
Create ProcessingInstruction node with target myInstruction and
value action silent
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.14Building an XML document with the DOM. (Part 3)
Create CDATA node and append to root node
Write XML Document to myDocument.xml
Creates and returns Element node
Create Element FirstName with text Sue
Create Element LastName with text Green
51 // add a CDATA section
52 CDATASection cdata = document.createCDATASection(
53 "I can add <, >, and ?" );
54 root.appendChild( cdata );
55
56 try {
57
58 // write the XML document to a file
59 ( (XmlDocument) document).write( new FileOutputStream(
60 "myDocument.xml" ) );
61 }
62 catch ( IOException ioe ) {
63 ioe.printStackTrace();
64 }
65 }
66
67 public Node createContactNode( Document document )
68 {
69
70 // create FirstName and LastName elements
71 Element firstName = document.createElement( "FirstName" );
72 Element lastName = document.createElement( "LastName" );
73
74 firstName.appendChild( document.createTextNode( "Sue" ) );
75 lastName.appendChild( document.createTextNode( "Green" ) );
76
Create CDATA node and append to root node
Write XML Document to myDocument.xml
Creates and returns Element node
Create Element FirstName with
text Sue
Create Element LastName with
text Green
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.14Building an XML document with the DOM. (Part 4)
Create Element contact with attribute gender
Append Elements FirstName and LastName to Element contact
Return Element contact
Output for Fig. 8.14
77 // create contact element
78 Element contact = document.createElement( "contact" );
79
80 // create an attribute
81 Attr genderAttribute = document.createAttribute( "gender" );
82 genderAttribute.setValue( "F" );
83
84 // append attribute to contact element
85 contact.setAttributeNode( genderAttribute );
86 contact.appendChild( firstName );
87 contact.appendChild( lastName );
88 return contact;
89 }
90
91 public static void main( String args[] )
92 {
93 BuildXml buildXml = new BuildXml();
94 }
95 }
Create Element contact with attribute gender
Append Elements FirstName and LastName to Element
contact
Return Element contact
javac BuildXml.javajava BuildXml
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.14Output for buildXml.java.
1 <?xml version = "1.0" encoding = "UTF-8"?>
2
3 <root>
4 <!--This is a simple contact list-->
5 <contact gender = "F">
6 <FirstName>Sue</FirstName>
7 <LastName>Green</LastName>
8 </contact>
9 <?myInstruction action silent?>
10 <![CDATA[I can add <, >, and ?]]>
11 </root>
2002 Prentice Hall, Inc. All rights reserved.
8.7 Traversing the DOM
• Use DOM to traverse XML document– Output element nodes
– Output attribute nodes
– Output text nodes
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.15Traversing the DOM.
Obtain JAXP default parser and DocumentBuilder to load and parse XML documents
1 // Fig. 8.15 : TraverseDOM.java
2 // Traverses DOM and prints various nodes.
3
4 import java.io.*;
5 import org.w3c.dom.*;
6 import org.xml.sax.*;
7 import javax.xml.parsers.*;
8 import com.sun.xml.tree.XmlDocument;
9
10 public class TraverseDOM {
11 private Document document;
12
13 public TraverseDOM( String file )
14 {
15 try {
16
17 // obtain the default parser
18 DocumentBuilderFactory factory =
19 DocumentBuilderFactory.newInstance();
20 factory.setValidating( true );
21 DocumentBuilder builder = factory.newDocumentBuilder();
22
23 // set error handler for validation errors
24 builder.setErrorHandler( new MyErrorHandler() );
25
Obtain JAXP default parser and DocumentBuilder to load and
parse XML documents
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.15Traversing the DOM. (Part 2)
Load and parse XML document
Pass Document to method processNode
Outputs information about argument Node and child elements
switch statement determines Node type
26 // obtain document object from XML document
27 document = builder.parse( new File( file ) );
28 processNode( document );
29 }
30 catch ( SAXParseException spe ) {
31 System.err.println(
32 "Parse error: " + spe.getMessage() );
33 System.exit( 1 );
34 }
35 catch ( SAXException se ) {
36 se.printStackTrace();
37 }
38 catch ( FileNotFoundException fne ) {
39 System.err.println( "File \'"
40 + file + "\' not found. " );
41 System.exit( 1 );
42 }
43 catch ( Exception e ) {
44 e.printStackTrace();
45 }
46 }
47
48 public void processNode( Node currentNode )
49 {
50 switch ( currentNode.getNodeType() ) {
51
Load and parse XML document
Pass Document to method processNode
Outputs information about argument Node
and child elements
switch statement determines Node type
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.15Traversing the DOM. (Part 3)
If document node, output document node and process child nodes
If element node, output element’s attributes and process child nodes
52 // process a Document node53 case Node.DOCUMENT_NODE:54 Document doc = ( Document ) currentNode;5556 System.out.println( 57 "Document node: " + doc.getNodeName() +58 "\nRoot element: " +59 doc.getDocumentElement().getNodeName() );60 processChildNodes( doc.getChildNodes() );61 break;6263 // process an Element node64 case Node.ELEMENT_NODE: 65 System.out.println( "\nElement node: " + 66 currentNode.getNodeName() );67 NamedNodeMap attributeNodes =68 currentNode.getAttributes();6970 for ( int i = 0; i < attributeNodes.getLength(); i++){
71 Attr attribute = ( Attr ) attributeNodes.item( i );
7273 System.out.println( "\tAttribute: " + 74 attribute.getNodeName() + " ; Value = " +75 attribute.getNodeValue() );76 }7778 processChildNodes( currentNode.getChildNodes() );79 break;80
If document node, output document node
and process child nodes
If element node, output element’s attributes and
process child nodes
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.15Traversing the DOM. (Part 4)
If CDATA or text node, output node’s text content
Method process-ChildNodes calls method processNode for each Node in NodeList
Method main starts program
81 // process a text node and a CDATA section82 case Node.CDATA_SECTION_NODE:83 case Node.TEXT_NODE: 84 Text text = ( Text ) currentNode;8586 if ( !text.getNodeValue().trim().equals( "" ) )87 System.out.println( "\tText: " +88 text.getNodeValue() );89 break;90 }91 }9293 public void processChildNodes( NodeList children )94 {95 if ( children.getLength() != 0 ) 9697 for ( int i = 0; i < children.getLength(); i++)98 processNode( children.item( i ) );99 }100101 public static void main( String args[] )102 {103 if ( args.length < 1 ) {104 System.err.println( 105 "Usage: java TraverseDOM <filename>" );106 System.exit( 1 );107 }108109 TraverseDOM traverseDOM = new TraverseDOM( args[ 0 ] ); 110 }111}
If CDATA or text node, output node’s text content
Method processChildNodes calls method processNode for
each Node in NodeList
Method main starts program
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.16Sample execution for TraverseDOM.java.
TraverseDOM application traverses simpleContact.xml
1 <?xml version = "1.0"?>
2
3 <!-- Fig 8.16 : simpleContact.xml -->
4 <!-- Input file for traverseDOM.java -->
5
6 <!DOCTYPE contacts [
7 <!ELEMENT contacts ( contact+ )>
8 <!ELEMENT contact ( FirstName, LastName )>
9 <!ATTLIST contact gender ( M | F ) "M">
10 <!ELEMENT FirstName ( #PCDATA )>
11 <!ELEMENT LastName ( #PCDATA )>
12 ]>
13
14 <contacts>
15 <contact gender = "M">
16 <FirstName>John</FirstName>
17 <LastName>Black</LastName>
18 </contact>
19 </contacts>
TraverseDOM application traverses simpleContact.xml
2002 Prentice Hall, Inc. All rights reserved.
8.8 Case Study: Modifying the Day Planner Application to Use the DOM
• Continue enhancing day-planner application– Java-based
• Create graphical user interface (GUI)
• Create class that uses DOM to query day planner
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM.
Reference to GUI component that displays output
Reference to GUI component that displays output
Constructor initializes application (loads and parses day planner)
1 // Fig. 8.17 : DOMPlanner.java
2 // A day planner application using DOM.
3 // The following program uses Sun's validating parser.
4
5 import java.io.*;
6 import java.awt.*;
7 import java.util.*;
8 import javax.swing.*;
9
10 import org.w3c.dom.*;
11 import org.xml.sax.*;
12 import javax.xml.parsers.*;
13 import com.sun.xml.tree.XmlDocument;
14
15 public class DOMPlanner {
16
17 private JTextArea display; // for displaying output
18 private InputSource input; // for reading the XML document
19 private Document document; // document node object
20
21 // variables to store the query parameters and the result
22 private int year, month, day, timePeriod;
23 private String resultYear, resultDay;
24
25 public DOMPlanner( JTextArea output )
26 {
27 year = month = day = timePeriod = -1;
28 display = output;
29
Constructor initializes application (loads and parses day planner)
Reference to GUI component that displays output
Reference to parsable XML document
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM. (Part 2)
Obtain JAXP default parser and DocumentBuilder to load and parse XML documents
30 try {3132 // obtain the default parser33 DocumentBuilderFactory factory =34 DocumentBuilderFactory.newInstance();35 factory.setValidating( true );36 DocumentBuilder builder = factory.newDocumentBuilder();3738 // set error handler for validation errors39 builder.setErrorHandler( new MyErrorHandler() );4041 // obtain document object from XML document42 document = builder.parse( new File( "planner.xml" ) );43 } 44 catch ( SAXParseException spe ) {45 System.err.println( "Parse error: " + 46 spe.getMessage() );47 System.exit( 1 );48 }49 catch ( SAXException se ) {50 se.printStackTrace(); 51 }52 catch ( FileNotFoundException fne ) {53 System.err.println( "File \"planner.xml\" not found." );54 System.exit( 1 );55 }56 catch ( Exception e ) {57 e.printStackTrace();58 }59 }60
Obtain JAXP default parser and DocumentBuilder to load and
parse XML documents
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM. (Part 3)
Returns String array containing day-planner document’s years
Retrieve XML document’s root element (planner)
Place all year elements in NodeList
Create String from year elements in NodeList
“Split” space-delimited String into String array
61 // method to get the available years from the XML file
62 public String[] getYears()
63 {
64 String availableYears[];
65 StringTokenizer tokens;
66 String str = " ";
67 int i = 0;
68
69 Element root = document.getDocumentElement();
70 NodeList yearNodes =
71 root.getElementsByTagName( "year" );
72
73 // get value of attribute 'value' for each 'year' node
74 for ( i = 0; i < yearNodes.getLength(); i++ ) {
75 NamedNodeMap yearAttributes =
76 yearNodes.item( i ).getAttributes();
77
78 str += " " + yearAttributes.item( 0 ).getNodeValue();
79 }
80
81 tokens = new StringTokenizer( str );
82 availableYears = new String[ tokens.countTokens() + 1 ];
83 availableYears[ 0 ] = "ANY";
84 i = 1;
85
86 // form an array of strings containing available years
87 while ( tokens.hasMoreTokens() )
88 availableYears[ i++ ] = tokens.nextToken();
89
Returns String array containing day-planner
document’s years
Retrieve XML document’s root element (planner)
Place all year elements in NodeList
Create String from year elements in NodeList
“Split” space-delimited String into String array
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM. (Part 4)
Return String array containing document’s years
Initialize variables (e.g., year, month, etc.) used in query
Call method getResult to process XML document (output query result)
Determine Node type
If Document Node, process Node’s children recursively
90 return availableYears;91 }9293 // method to initialize the query94 public void getQueryResult( int y, int m, int d, int t )95 {96 year = y;97 month = m;98 day = d;99 resultYear = "";100 resultDay = "";101 timePeriod = t;102 display.setText( "*** YOUR DAY PLANNER ***" );103 getResult( document );104 } 105106 // method to output the result of query107 public void getResult( Node node )108 {109 // process each type of node110 // if the node contains child nodes, 111 // process it recursively112 switch ( node.getNodeType() ) {113114 // if it is a Document node process its children115 case Node.DOCUMENT_NODE:116 Document doc = ( Document ) node;117118 getResult( doc.getDocumentElement() );119 break;120
Return String array containing document’s years
Initialize variables (e.g., year, month, etc.) used in query
Call method getResult to process XML document (output query result)
Determine Node type
If Document Node, process Node’s children recursively
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM. (Part 5)
If Element Node, process Node’s according to its name
If planner, process planner’s children
If year, process year’s children
If date, get attributes month and day, then process date’s children
121 // process element node according to its tag name122 case Node.ELEMENT_NODE:123124 if ( node.getNodeName().equals( "planner" ) )125 processChildNodes( node.getChildNodes() );126 else if ( node.getNodeName().equals( "year" ) ) {127128 // find the attribute value for year and 129 // check if it matches the query130 NamedNodeMap yearAttributes = 131 node.getAttributes();132 Node value = yearAttributes.item( 0 );133134 if ( Integer.parseInt( value.getNodeValue() )135 == year || year == -1 ) {136 resultYear = " Y " +137 Integer.parseInt( value.getNodeValue() );138 processChildNodes( node.getChildNodes() );139 }140 else141 return; 142143 }144 else if ( node.getNodeName().equals( "date" ) ) {145 Element dateElement = ( Element ) node;146 int m = Integer.parseInt( 147 dateElement.getAttribute( "month" ) );148 int d = Integer.parseInt( 149 dateElement.getAttribute( "day" ) );150
If Element Node, process Node’s according to its name
If planner, process planner’s children
If year, process year’s children
If date, get attributes month and day, then process date’s children
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM. (Part 6)
If note, get attributes
151 // check if the current 'date' node satisfies query
152 if ( ( m == month && d == day ) ||
153 ( month == -1 && d == day ) ||
154 ( m == month && day == -1 ) ||
155 ( month == -1 && day == -1 ) ) {
156 resultDay = "DATE: D " + d + " M " + m ;
157 processChildNodes(
158 dateElement.getChildNodes() );
159 }
160 else
161 return;
162
163 }
164 else if ( node.getNodeName().equals( "note" ) ) {
165
166 // fetch attributes for the note node and
167 // verify its attribute values with the query
168 NamedNodeMap noteAttributes =
169 node.getAttributes();
170
171 int scheduleTime;
172
If note, get attributes
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM. (Part 7)
Get note appointment time if one was scheduled (i.e., attribute time is present)
If time matches query, display date, time and appointment information
173 if ( noteAttributes.getLength() != 0 ) {
174 Node nodeTime = noteAttributes.item( 0 );
175
176 scheduleTime =
177 Integer.parseInt( nodeTime.getNodeValue() );
178 }
179 else
180 scheduleTime = -1;
181
182 // if the time lies between the periods of the
183 // day display the value of node 'note'
184 if ( isBetween( scheduleTime ) ) {
185 Node child =
186 ( node.getChildNodes() ).item( 0 );
187 String s =
188 child.getNodeValue().trim();
189
190 display.append( "\n" + resultDay +
191 resultYear );
192
193 if ( scheduleTime != -1 )
194 display.append( "\nTIME: " +
195 scheduleTime +" > " + s );
196 else
197 display.append( "\nALL DAY > " + s );
198
Get note appointment time if one was scheduled (i.e.,
attribute time is present)
If time matches query, display date, time and
appointment information
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM. (Part 8)
Iterate and process NodeList (i.e., element’s child nodes)
199 display.append( "\n* * * * * * * * * *" );
200 }
201 else
202 return;
203 }
204 break;
205 }
206 }
207
208 // method to process child nodes
209 public void processChildNodes( NodeList children )
210 {
211 if ( children.getLength() != 0 )
212
213 for ( int i = 0; i < children.getLength(); i++ )
214 getResult( children.item( i ) );
215
216 return;
217 }
218
Iterate and process NodeList (i.e., element’s child nodes)
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM. (Part 9)
Check time value of appointment against query
219 // method to compare the time with various periods
220 // of the day
221 public boolean isBetween( int time )
222 {
223 switch ( timePeriod ) {
224
225 case -1: // add day
226 return true;
227
228 case 0: // morning
229
230 if ( time >= 500 && time < 1200 )
231 return true;
232
233 break;
234
235 case 1: // afternoon
236
237 if ( time >= 1200 && time < 1800 )
238 return true;
239
240 break;
241
242 case 2: // evening
243
Check time value of appointment against query
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.17Day planner using DOM. (Part 10)
244 if ( time >= 1800 && time < 2100 ) 245 return true;246247 break;248249 case 3: // night250251 if ( time >= 2100 || time < 500 )252 return true;253254 break;255256 default:257 System.out.println( "Illegal time in XML file" );258 }259260 return false;261 }262}
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.18Interface for day planner.
Create GUI
Instantiate DOMPlanner object
1 // Fig. 8.18 : DayPlanner.java2 // Program for GUI interface for the day planner application.34 import java.awt.*; 5 import java.awt.event.*; 6 import javax.swing.*; 7 import javax.swing.event.*;89 public class DayPlanner extends JFrame10 implements ActionListener {1112 // GUI components13 private JTextArea display;14 private JComboBox year, month, day, time;15 private JButton query;16 private JPanel panel1, panel2;17 private DOMPlanner handler;1819 public DayPlanner()20 {21 super( "Day planner using DOM" );2223 // set the output font 24 Font font = new Font( "Monospaced",25 java.awt.Font.BOLD, 16 );26 display = new JTextArea();27 display.setFont( font );28 display.setEditable( false );29 30 handler = new DOMPlanner( display );31
Create GUI
Instantiate DOMPlanner object
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.18Interface for day planner. (Part 2)
Populate JComboBox with method getYears of class DOMPlanner
Create other JComboBoxs and populate them with month, day and time, respectively
32 // initialize the user interface components
33 year = new JComboBox( handler.getYears() );
34
35 String months[] = new String[ 13 ];
36 months[ 0 ] = "ANY";
37
38 for ( int i = 1; i < 13; i++ )
39 months[ i ] = Integer.toString( i );
40
41 month = new JComboBox( months );
42
43 String days[] = new String[ 32 ];
44 days[ 0 ] = "ANY";
45
46 for ( int i = 1; i < 32; i++ )
47 days[ i ] = Integer.toString( i );
48
49 day = new JComboBox( days );
50
51 String times[] = { "ANY", "Morning", "Afternoon",
52 "Evening", "Night" };
53 time = new JComboBox( times );
54
55 query = new JButton( "Get Schedules" );
56 query.addActionListener( this );
57
Populate JComboBox with method getYears of class
DOMPlanner
Create other JComboBoxs and populate them with month, day
and time, respectively
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.18Interface for day planner. (Part 3)
58 // panel containing components for querying
59 panel1 = new JPanel();
60 panel1.setLayout( new GridLayout( 4, 2 ) );
61 panel1.add( new JLabel( "Year" ) );
62 panel1.add( year );
63 panel1.add( new JLabel( "Month" ) );
64 panel1.add( month );
65 panel1.add( new JLabel( "Day" ) );
66 panel1.add( day );
67 panel1.add( new JLabel("Time") );
68 panel1.add( time );
69
70 // panel containing text area for output
71 // and panel2 containing other GUI components.
72 panel2 = new JPanel();
73 panel2.setLayout( new GridLayout( 1, 2 ) );
74 panel2.add( panel1 );
75 panel2.add( query );
76
77 Container c = getContentPane();
78 c.setLayout( new BorderLayout() );
79 c.add( new JScrollPane( display ), BorderLayout.CENTER );
80 c.add( panel2, BorderLayout.SOUTH );
81 setSize( 600, 450 );
82 show();
83 }
84
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.18Interface for day planner. (Part 4)
Method action-Performed is invoked when user presses Get Schedules button
JComboBox values are passed to method getQueryResult of class DOMPlanner to perform query
85 // method executed when query button is pressed86 public void actionPerformed( ActionEvent e )87 {88 if ( e.getSource() == query ) {89 int yearIndex, monthIndex, dayIndex, timeIndex;9091 // get the integer values of all the query parameters92 yearIndex =93 getIntegerValue( ( String ) year.getSelectedItem() );
94 monthIndex =95 getIntegerValue( ( String ) month.getSelectedItem() );
96 dayIndex =97 getIntegerValue( ( String ) day.getSelectedItem() );98 timeIndex = time.getSelectedIndex() - 1;99100 // get the result of query101 handler.getQueryResult( yearIndex, monthIndex,102 dayIndex, timeIndex );103 }104 }105106 // method to convert the string value to integer107 public int getIntegerValue( String str )108 {109 // if the value 'ANY' is selected, return -1110 if ( str.equals( "ANY" ) )111 return -1;112 else113 return Integer.parseInt( str );114 }115
Method actionPerformed is invoked when user presses
Get Schedules button
JComboBox values are passed to method getQueryResult
of class DOMPlanner to perform query
2002 Prentice Hall, Inc. All rights reserved.
Outline
Fig. 8.18Interface for day planner. (Part 5)
116 public static void main( String s[] )
117 {
118 DayPlanner d = new DayPlanner();
119
120 d.addWindowListener(
121 new WindowAdapter()
122 {
123 public void windowClosing( WindowEvent e )
124 {
125 System.exit( 0 );
126 }
127 }
128 );
129 }
130}
2002 Prentice Hall, Inc. All rights reserved.
Output for Fig. 8.18