text: Chapter 23: XML.
  A Bit of Background.
  Text Versus Binary
  When Tim Berners-Lee began postulating the Web back at CERN in the late 1980s, he wanted to organize project information using hypertext.[1].
  A Universal Parserclass State.
  The XML APIs
  As of Java 1.4, all the basic APIs for working with XML are bundled with Java. This includes the
  javax.xmlstandard extension packages for working with Simple API for XML (SAX), Document Object Model (DOM), and Extensible Stylesheet Language (XSL) transforms. If you are using an older version of Java, you can still use all these tools, but you will have to download the packages separately from.
  XML and Web Browsers.
  XML Basics/>
  Attributeselement in our snippet above, the attributes
  typeand
  IDrepresent metadata about the document. We might expect that a Java class representing the
  Documentwould have static identifiers for document types such as
  LEGAL. In the case of the
  Imageelement, the attribute is simply a more compact way of including the filename. As a rule, attributes should be atomic, with no significant internal structure; by contrast, child elements can have arbitrary complexity.
  XML Documents.
  Encoding.
  Namespacesattribute,namespace attribute can be applied to an element and all its children; this is called a default namespace for the element:
  <body xmlns="">
  But more often it is desirable to specify namespaces on a tag-by-tag basis. To do this, we can use the
  xmlnsattribute.
  Validation.
  HTML to XHTML.
  SAX
  SAX is a low-level, event-style mechanism for parsing XML documents. SAX originated in Java but has been implemented in many languages.
  The SAX API
  To use SAX, we'll be using classes from the
  org.xml.saxpackage, available from the W3C (World Wide Web Consortium). To perform the actual parsing, we'll need the
  javax.xml.parserspackage, which is the standard Java package for accessing XML parsers. The
  java.xml.parserspackage is part of the Java API for XML Processing (JAXP), which allows different parser implementations to be used with Java.
  To read an XML document with SAX, we first register an
  org.xml.sax.ContentHandlerclass with the parser. The
  ContentHandlerhasclass.
  public void startElement(
  String namespace, String localname, String qname, Attributes atts );
  public void characters(
  char[] ch, int start, int len );
  public void endElement(
  String namespace, String localname, String qname );
  The
  qnameparameter is the qualified name of the element. This is the element name, prefixed with namespace if it has one. When working with namespaces, the
  namespaceand
  localnameparameters are also supplied, providing the namespace and unqualified name.
  The
  ContentHandlerinterface.
  JAXP
  To perform the parsing, we'll need to get a parser from the
  javax.xml.parserspackage. The process of getting a parser is abstracted through a factory pattern, allowing different parser implementations to be plugged into the Java platform. The following snippet constructs a
  SAXParserobject and an
  XMLReaderusedarserto have the
  parsemethod. The
  XMLReaderintermediary.
  SAX's strengths and weaknesses.
  Building a Model Using SAX
  The
  ContentHandlermechanism.
  Building the XML file.
  The modelodertool.) For convenience, we'll have our model objects extend a base
  SimpleElementclass).
  SAX model builder
  Now let's get down to business and write our builder tool. The
  SAXModelBuilderweBuilderextends
  DefaultHandlerto help us implement the
  ContentHandlerinterface.object). Failing that, we look for an "add" or "set" method accepting a
  Stringargument and use it to apply any text content of the child object. This convenience saves us from having to create trivial classes for properties containing only text.
  The common base class
  SimpleElementhelps us in two ways. First, it provides a method allowing us to pass attributes to the model class. Next, we use
  SimpleElementas a placeholder when no class exists for an element, allowing us to store the text of the tag.
  Test drive
  Finally, we can test-drive the model builder with the following class,
  TestModelBuilder, which calls the SAX parser, setting an instance of our
  SAXModelBuilder.
  Limitations and possibilities.
  XMLencoder/decoder
  Java 1.4 introduced a tool for serializing JavaBeans classes to XML. The
  java.beanspackage
  XMLEncoderand
  XMLDecoderclasses are analogous to
  java.io
  ObjectInputStreamattempts to construct a copy of the graph of beans that you are serializing, using only public constructors and JavaBean properties. As it works, it writes out these steps as "instructions" in an XML format. Later, the
  XMLDecoderexecutesusesclass, which will populate the beans for you to write:
  import java.beans.XMLEncoder;
  XMLEncoder xmle = new XMLEncoder( System.out );
  xmle.writeObject(inventory);
  xmle.close( );
  Fun!
  Further thoughts
  It might seem at first like this would obviate the need for our
  SAXModelBuilderexample. Why not simply write our XML in the format that
  XMLDecoderunderstands and use it to build our model? Well, although
  XMLEncoderodercand
  Attributeswith DOM API
  The core DOM classes belong to the
  org.w3c.dompackage. The result of parsing an XML document with DOM is a
  Documentobject from this package (see Figure 23-1). The
  Documentis a factory and a container for a hierarchical collection of
  Nodeobjects, representing the document structure. A node has a parent and may have children, which can be traversed using its
  getChildNodes(),
  getFirstChild(), or
  getLastChild()methods. A node may also have "attributes" associated with it, which consist of a named map of nodes.
  Subtypes ofSubtypes of
  Node--
  Element,
  Text, and
  Attr--represent elements, text, and attributes in XML. Some types of nodes (including these) have a text "value." For example, the value of a
  Textnode is the text of the element it represents. The same is true of an
  attribute,
  cdata, or
  commentnode. The value of a node can be accessed by the
  getNodeValue()and
  setNodeValue()methods.
  The
  Elementnode provides "random" access to its child elements through its
  getElementsByTagName()method, which returns a
  NodeList(a simple collection type).
  You can also fetch an attribute by name from theYou can also fetch an attribute by name from the
  Elementusing the
  getAttribute()method.
  The
  javax.xml.parserspackage contains a factory for DOM parsers, just as it does for SAX parsers. An instance of
  DocumentBuilderFactorycan be used to create a
  DocumentBuilderobject to parse the file and produce a
  Documentresult.
  Test-Driving DOMclass:
  mportcreates an instance of a
  DocumentBuilderand uses it to parse our zooinventory.xml file.
  We use theWe use the
  Document
  getDocumentElement()method to get the root element of the document, from which we will begin our traversal. From there, we ask for all the
  Animalchild nodes. The
  getElementbyTagName()method returns a
  NodeListobject,from the second animal. We use it to fetch a
  NodeListfor the tags matching
  Ingredientand print them as before. The output should contain the same information as our SAX-based example.
  Generating XML with DOMpackage. aNote that the imports are almost as long as the entire program! Here we are using an instance of a
  Transformerobject in its simplest capacity to copy from a source to an output. We'll return to the
  Transformerlater when we discuss XSL.
  JDOMfor.
  Validating Documents
  .
  Using Document Validation.
  DTDs.
  Attributes of an element are defined with the
  <!ATTLIST>tag. This tag enables the DTD to enforce rules about attributes. It accepts a list of identifiers and a default value:
  <!ATTLIST Animal class (unknown | mammal | reptile) "unknown">
  This
  ATTLISTsays that the
  Animalelement has a
  classattribute that can have one of three values:
  unknown,
  mammal, or
  reptile. The default is
  unknown.consists of any number of
  Animalelements. An
  Animalhas a
  Name,
  Species, and
  Habitattag followed by either a
  Foodor
  FoodRecipe.
  FoodRecipe's structure is further defined later.
  To use our DTD, we must associate it with the XML document. We do this by placing a
  DOCTYPEdeclaration in the XML itself. When a validating parser encounters the
  DOCTYPE, it attempts to load the DTD and validate the document. There are several forms the
  DOCTYPEcan have, but the one we'll use is:
  <!DOCTYPE Inventory SYSTEM "zooinventory.dtd">
  Both SAX and DOM parsers can automatically validate documents that contain a
  DOCTYPEdeclaration. However, you have to explicitly ask the parser factory to provide a parser that is capable of validation. To do this, set the validating property of the parser factory to
  truebefore you ask it for an instance of the parser. For example:.
  To really use the validation, we would have to register an
  org.xml.sax.ErrorHandlerobject with the parser, but by default Java installs one that simply prints the errors for us.
  XML Schema.
  JAXB and Code Generation.
  XSL/XSLT
  Earlier in this chapter, we used a
  Transformerobject to copy a DOM representation of an example back to XML text. We mentioned then that we were not really tapping the potential of the
  Transformer. Now we'll give you the full story.
  The
  javax.xml.transformpackage Basicsfor the XSL namespace. Within the stylesheet are one or more template tags containing a
  matchattributeattribute can refer to elements in a hierarchical path fashion starting with the root. For example,
  match="/Inventory/Animal"would match only the
  Animalelements from our zooinventory.xml file. The path may be absolute (starting with "/") or relative, in which case the template detects whenever that element appears in any context. The
  matchattributeThe XSL
  value-oftag is used to output the content of an element or a child of the element. For example, the following template would match an
  Animalelement and output the value of its
  Namechild:
  <xsl:template
  Name: <xsl:value-of
  </xsl:template>
  The
  selectattribute uses a similar expression format to match. Here we tell it to print the value of the
  Nameelement within
  Animal. We could have used a relative path to a more deeply nested element within
  Animalor even an absolute path to another part of the document. To refer to its own element, we can simply use "." as the path. The
  selectexpression can also retrieve attributes from the elements it refers to.
  Now if we try to add the
  Animaltemplate-templatestag.-templatestag. But upon invoking it, the template matching continues from the current node. Next we'll use what we have so far and add a few bells and whistles.
  Transforming the Zoo Inventoryand outputs the beginning of our HTML document (the header) along with the start of a table for the animals. It then delegates using
  apply-templatesbefore closing the table and adding the HTML footer. The next template matches
  Inventory/Animal, printing one row of an HTML table for each animal. Although there are no other
  Animalelements in the document, it still doesn't hurt to specify that we will match an
  Animalonly in the context of an
  Inventory, because in this case we are relying on
  Animalto start and end our table. (This template makes sense only in the context of an
  Inventory.) Finally, we provide a template that matches
  FoodRecipeand prints a small (nested) table for that information.
  FoodRecipemakes use of the
  for-eachoperation to loop over child nodes with a
  selectspecifying that we are only interested in
  Ingredientchildren. For each
  Ingredient, we output its value in a row.
  There is one more thing to note in the
  Animaltemplate. Our
  apply-templateselement has a
  selectattribute that limits the elements affected. In this case, we are using the "
  |" regular expression-like syntax to say that we want to apply templates for only the
  Foodor
  FoodRecipechild elements. Why do we do this? Because we didn't match the root of the document (only
  Inventory), we still have the default stylesheet behavior of outputting the plain text of nodes that aren't matched. We want this behavior for the
  Foodelement in the event that a
  FoodRecipeisn't there. But we don't want it for all the other elements of
  Animalthat we've handled explicitly. Alternatively, we could have been more verbose, adding a template matching the root and another template just for the
  Foodelement..
  XSLTransform
  Now that we have a stylesheet, let's apply it! The following simple program,
  XSLTransform, uses the
  javax.xml.transformpackage.
  Constructing the transform is a similar process to that of getting a SAX or DOM parser. The difference from our earlier use of the
  TransformerFactoryis that this time we construct the transformer, passing it the XSL stylesheet source. The resulting
  Transformerobject is then a dedicated machine that knows how to take input XML and generate output according to its rules.
  One important thing to note about
  XSLTransformis that it is not guaranteed thread-safe. If you must make concurrent transformations in many threads, they must either coordinate their use of the transformer or have their own instances.
  XSL in the Browser
  With our
  XSLTransformexample,.
  Web Services.
  1. To read Berners-Lee's original proposal to CERN, go to.
  Back to: Learning Java, 2nd Edition
  © 2001, O'Reilly & Associates, Inc.
  webmaster@oreilly.com