站内搜索: 请输入搜索关键词
当前页面: 图书首页 > XML and Java: Developing Web Applications, Second Edition

XML and Java: Developing Web Applications, Second Edition

[ directory ] Previous Section Next Section

3.3 Validating a Generated DOM Tree

The DOM tree created in Section 3.2 is well-formed. However, suppose some applications require that the document be valid. How can we accomplish this?

In the first edition of this book, we introduced a programming example for checking validation incrementally while creating a DOM tree. XML for Java versions 1 and 2 provide the validating generation feature for the purpose. However, Xerces does not support validating generation, because the DOM specification does not support the function. However, we believe the feature is very important for developing Web applications. Therefore, in this book we provide another way to validate a generated document.

The program ValidateCreatedTree, shown in Listing 3.5, creates a DOM tree, serializes it as a string that represents an XML document, and validates it. Xerces provides the DocumentType interface and its implementation to represent doctype information. It is added in the creation phase. We know it is a quick and dirty way to validate a generated document, but it is useful.

Listing 3.5 Validating a created DOM tree, chap03/ValidateCreatedTree. java
       package chap03;
       /**
        *       ValidateCreatedTree.java
        **/
       import java.io.StringWriter;
       import java.io.StringReader;
       import javax.xml.parsers.DocumentBuilderFactory;
       import javax.xml.parsers.DocumentBuilder;
       import org.w3c.dom.Document;
       import org.w3c.dom.DOMImplementation;
       import org.w3c.dom.Element;
       import org.w3c.dom.Text;
       import org.w3c.dom.ProcessingInstruction;
       import org.w3c.dom.DocumentType;
       import org.apache.xml.serialize.Serializer;
       import org.apache.xml.serialize.XMLSerializer;
       import org.apache.xml.serialize.OutputFormat;
       import org.apache.xerces.dom.DocumentImpl;
       import org.apache.xerces.parsers.DOMParser;
       import org.xml.sax.SAXException;
       import org.xml.sax.InputSource;
       import share.util.MyErrorHandler;

       public class ValidateCreatedTree {
          public static void main(String[] argv) {
              try {
                 // Creates document builder factory
                 DocumentBuilderFactory factory =
                     DocumentBuilderFactory.newInstance();
                 factory.setValidating(true);
                 // Tells the parser to be aware of namespaces
                 factory.setNamespaceAware(true);
                 // Creates builder object
                 DocumentBuilder builder =
                     factory.newDocumentBuilder();
                 // Sets an ErrorHandler
                 builder.setErrorHandler(new MyErrorHandler());

[39]             // DOMImplementation is used to get doctype object
[40]             DOMImplementation domImpl = builder.
                 getDOMImplementation();
[41]             // Creates Document Type Definition
[42]             DocumentType docType = domImpl.createDocumentType(
[43]                 "department",
[44]                 null,
[45]                 "chap03/department.dtd");
[46]              Document doc = domImpl.createDocument(null, "department",
[47]                 docType);
[48]
                 // Gets <department> element as document element
                 Element root = doc.getDocumentElement();

                 // Creates comment node
                 root.appendChild(doc.createComment(
                    "The first employee description."));

                 // Creates <employee> elements and its text content,
                 // and adds it
                 Element employee = doc.createElement("employee");
                 employee.setAttribute("id", "J.D");
                 root.appendChild(employee);

                 // Create Processing Instruction
                 root.appendChild(doc.createProcessingInstruction(
                      "application", "commandForApp"));

                 // Creates <name> element and adds it
                 Element name = doc.createElement("name");
                 name.appendChild(doc.createTextNode("John Doe"));
                 employee.appendChild(name);

                 // Creates <email> element and adds it
                 Element email = doc.createElement("email");
                 email.appendChild(doc.createTextNode(
                    "John.Doe@foo.com"));
                 employee.appendChild(email);

[77]             // Serializes the DOM tree as an XML document
[78]             OutputFormat formatter = new OutputFormat();
[79]
[80]             // The XML document will be serialized as string
[81]             StringWriter out = new StringWriter() ;
[82]             XMLSerializer serializer =
[83]                new XMLSerializer(out, formatter);
[84]             formatter.setPreserveSpace(true);
[85]             serializer.serialize(doc);
[86]             out.flush();
[87]             out.close() ;
[88]
[89]             // Parses the document
[90]             try {
[91]                builder.parse(new InputSource(
[92]                   new StringReader(out.getBuffer().toString())));
                    System.out.println(out.getBuffer().toString());
                 } catch (SAXException ex) {
                    ex.printStackTrace();
                 }
             } catch (Exception e) {
                 e.printStackTrace();
            }
        }
     }

The first half of the program is the same as MakeDocumentWithFactory, shown in Listing 3.2. Let's look at the original part, which begins with line 39.

First, we create a DocumentType object and append it as the child of the Document object. The DocumentType is specified in the DOM Level 2 specification, but a method to create the object is not specified. Therefore, we use a factory method defined by the org.apache.xerces.dom.DocumentImpl class, which comes from Xerces.

public DocumentType
createDocumentType(java.lang.String qualifiedName,
java.lang.String publicID,
                java.lang.String systemID)
throws DOMException

The first argument of this method is the name of the root element. It should be qualified with a prefix if the document contains namespaces. The second and third arguments take a public or system identifier, respectively (one should be specified and the other is null). In Listing 3.5, the name of the DTD file is specified as a system identifier.

[42]   DocumentType docType = domImpl.createDocumentType(
                                      "department",
                                      null,
                                      "chap03/department.dtd");

In the next part, the generated DOM tree will be serialized as a string.

       // Serializes the DOM tree as an XML document
[78]   OutputFormat formatter = new OutputFormat();

       // The XML document will be serialized as string
[81]   StringWriter out = new StringWriter() ;
[82]   XMLSerializer serializer =
                     new XMLSerializer(out, formatter);
[84]   formatter.setPreserveSpace(true);
[85]   serializer.serialize(doc);

Note that a StringWriter object is set in the constructor for an XMLSerializer object (System.out is used in Listing 3.2).

Finally, the serialized XML document is parsed with the DTD (line 91).

[91]   builder.parse(new InputSource(
          new StringReader(out.getBuffer().toString())));

The following is the execution result.

R:\samples>java chap03.ValidateCreatedTree
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE department SYSTEM "department.dtd">
<department><!--The first employee description.--><employee id="J.D">
<name>John
Doe</name><email>John.Doe@foo.com</email></employee><?application
commandForApp?
></department>
    [ directory ] Previous Section Next Section