7. Example: Tree Diagram 1 // Fig. 9.3 : Tree.java 2 // Using the SAX Parser to generate a tree diagram. 3 4 import java.io.*; 5 import org.xml.sax.*; // for HandlerBase class 6 import javax.xml.parsers.SAXParserFactory; 7 import javax.xml.parsers.ParserConfigurationException; 8 import javax.xml.parsers.SAXParser; 9 10 public class Tree extends HandlerBase { 11 private int indent = 0; // indentation counter 12 13 // returns the spaces needed for indenting 14 private String spacer( int count ) 15 { 16 String temp = ""; 17 18 for ( int i = 0; i < count; i++ ) 19 temp += " "; 20 21 return temp; 22 } 23 24 // method called before parsing 25 // it provides the document location 26 public void setDocumentLocator( Locator loc ) 27 { 28 System.out.println( "URL: " + loc.getSystemId() ); 29 } 30 1 // Fig. 9.3 : Tree.java 2 // Using the SAX Parser to generate a tree diagram. 3 4 import java.io.*; 5 import org.xml.sax.*; // for HandlerBase class 6 import javax.xml.parsers.SAXParserFactory; 7 import javax.xml.parsers.ParserConfigurationException; 8 import javax.xml.parsers.SAXParser; 9 10 public class Tree extends HandlerBase { 11 private int indent = 0; // indentation counter 12 13 // returns the spaces needed for indenting 14 private String spacer( int count ) 15 { 16 String temp = ""; 17 18 for ( int i = 0; i < count; i++ ) 19 temp += " "; 20 21 return temp; 22 } 23 24 // method called before parsing 25 // it provides the document location 26 public void setDocumentLocator( Locator loc ) 27 { 28 System.out.println( "URL: " + loc.getSystemId() ); 29 } 30 import specifies location of classes needed by application Assists in formatting Override method to output parsed document’s URL
8. 31 // method called at the beginning of a document 32 public void startDocument() throws SAXException 33 { 34 System.out.println( "[ document root ]" ); 35 } 36 37 // method called at the end of the document 38 public void endDocument() throws SAXException 39 { 40 System.out.println( "[ document end ]" ); 41 } 42 43 // method called at the start tag of an element 44 public void startElement( String name, 45 AttributeList attributes ) throws SAXException 46 { 47 System.out.println( spacer( indent++ ) + 48 "+-[ element : " + name + " ]"); 49 50 if ( attributes != null ) 51 52 for ( int i = 0; i < attributes.getLength(); i++ ) 53 System.out.println( spacer( indent ) + 54 "+-[ attribute : " + attributes.getName( i ) + 55 " ] amp;quot;" + attributes.getValue( i ) + "amp;quot;" ); 56 } 57 Overridden method called when root node encountered Overridden method called when end of document is encountered Overridden method called when start tag is encountered Output each attribute’s name and value (if any)
9. 58 // method called at the end tag of an element 59 public void endElement( String name ) throws SAXException 60 { 61 indent--; 62 } 63 64 // method called when a processing instruction is found 65 public void processingInstruction( String target, 66 String value ) throws SAXException 67 { 68 System.out.println( spacer( indent ) + 69 "+-[ proc-inst : " + target + " ] amp;quot;" + value + "amp;quot;" ); 70 } 71 72 // method called when characters are found 73 public void characters( char buffer[], int offset, 74 int length ) throws SAXException 75 { 76 if ( length > 0 ) { 77 String temp = new String( buffer, offset, length ); 78 79 System.out.println( spacer( indent ) + 80 "+-[ text ] amp;quot;" + temp + "amp;quot;" ); 81 } 82 } 83 Overridden method called when end of element is encountered Overridden method called when processing instruction is encountered Overridden method called when character data is encountered
10. 84 // method called when ignorable whitespace is found 85 public void ignorableWhitespace( char buffer[], 86 int offset, int length ) 87 { 88 if ( length > 0 ) { 89 System.out.println( spacer( indent ) + "+-[ ignorable ]" ); 90 } 91 } 92 93 // method called on a non-fatal (validation) error 94 public void error( SAXParseException spe ) 95 throws SAXParseException 96 { 97 // treat non-fatal errors as fatal errors 98 throw spe; 99 } 100 101 // method called on a parsing warning 102 public void warning( SAXParseException spe ) 103 throws SAXParseException 104 { 105 System.err.println( "Warning: " + spe.getMessage() ); 106 } 107 108 // main method 109 public static void main( String args[] ) 110 { 111 boolean validate = false ; 112 Overridden method called when ignorable whitespace is encountered Overridden method called when error (usually validation) occurs Overridden method called when problem is detected (but not considered error) Method main starts application
13. URL: file:C:/Tree/spacing1.xml [ document root ] +-[ element : test ] +-[ attribute : name ] " spacing 1 " +-[ text ] " " +-[ text ] " " +-[ element : example ] +-[ element : object ] +-[ text ] "World" +-[ text ] " " [ document end ] 1 <?xml version = "1.0" ?> 2 3 <!-- Fig. 9.4 : spacing1.xml --> 4 <!-- Whitespaces in nonvalidating parsing --> 5 <!-- XML document without DTD --> 6 7 <test name = " spacing 1 " > 8 <example><object> World </object></example> 9 </test> Root element test contains attribute name with value “ spacing 1 ” XML document with elements test , example and object XML document does not reference DTD Note that whitespace is preserved: attribute value (line 7), line feed (end of line 7), indentation (line 8) and line feed (end of line 8)
14. URL: file:C:/Tree/spacing2.xml [ document root ] +-[ element : test ] +-[ attribute : name ] " spacing 2 " +-[ ignorable ] +-[ ignorable ] +-[ element : example ] +-[ element : object ] +-[ text ] "World" +-[ ignorable ] [ document end ] 1 <?xml version = "1.0" ?> 2 3 <!-- Fig. 9.5 : spacing2.xml --> 4 <!-- Whitespace and nonvalidated parsing --> 5 <!-- XML document with DTD --> 6 7 <!DOCTYPE test [ 8 <!ELEMENT test (example) > 9 <!ATTLIST test name CDATA #IMPLIED> 10 <!ELEMENT element (object*) > 11 <!ELEMENT object ( #PCDATA ) > 12 ]> 13 14 <test name = " spacing 2 " > 15 <example><object> World </object></example> 16 </test> DTD checks document’s characters, so any “removable” whitespace is ignorable Line feed at line 14, spaces at beginning of line 15 and line feed at line 15 are ignored
15. URL: file:C:/Tree/notvalid.xml [ document root ] +-[ element : test ] +-[ ignorable ] +-[ ignorable ] +-[ proc-inst : test ] "message" +-[ ignorable ] +-[ ignorable ] +-[ element : example ] +-[ element : item ] +-[ text ] "Hello & Welcome!" +-[ ignorable ] [ document end ] 1 <?xml version = "1.0" ?> 2 3 <!-- Fig. 9.6 : notvalid.xml --> 4 <!-- Validation and non-validation --> 5 6 <!DOCTYPE test [ 7 <!ELEMENT test (example) > 8 <!ELEMENT example ( #PCDATA ) > 9 ]> 10 11 <test> 12 <?test message?> 13 <example><item><![CDATA[ Hello & Welcome! ]]></item></example> 14 </test> Invalid document because element example cannot contain element item Validation disabled, so document parses successfully Parser does not process text in CDATA section and returns character data
16. URL: file:C:/Tree/notvalid.xml [ document root ] +-[ element : test ] +-[ ignorable ] +-[ ignorable ] +-[ proc-inst : test ] "message" +-[ ignorable ] +-[ ignorable ] +-[ element : example ] Parse Error: Element "example" does not allow "item" Parsing terminates when fatal error occurs at element item Validation enabled
17. URL: file:C:/Tree/valid.xml [ document root ] +-[ element : test ] +-[ text ] " " +-[ text ] " " +-[ element : example ] +-[ text ] "Hello " +-[ text ] "&" +-[ text ] " Welcome!" +-[ text ] " " [ document end ] URL: file:C:/Tree/valid.xml [ document root ] Warning: Valid documents must have a <!DOCTYPE declaration. Parse Error: Element type "test" is not declared. 1 <?xml version = "1.0" ?> 2 3 <!-- Fig. 9.7 : valid.xml --> 4 <!-- DTD-less document --> 5 6 <test> 7 <example> Hello & Welcome! </example> 8 </test> Validation disabled in first output, so document parses successfully Validation enabled in second output, and parsing fails because DTD does not exist