Oracle8i Application Developer's Guide - XML Release 3 (8.1.7) Part Number A86030-01 |
Library | Service | Contents | Index

Using XML Parser for Java, 15 of 22

## DOM and SAX APIs

### Using the DOM API

#### Question

How do I get the number of elements in a particular tag using the parser?

#### Answer

You can use the getElementsByTagName() method that returns a NodeList of all descent elements with a given tag name. You can then find out the number of elements in that NodeList to determine the number of the elements in the particular tag.

### How DOM Parser Works

#### Question

How does the XML DOM parser work?

#### Answer

The parser accepts an XML formatted document and constructs in memory a DOM tree based on its structure. It will then check whether the document is well-formed and optionally whether it complies with a DTD. It also provides methods to support DOM Level 1.

### Creating a Node With Value to be Set Later

#### Question

How do I create a node whose value I can set later?

#### Answer

If you check the DOM spec referring to the table discussing the node type, you will find that if you are creating an element node, its nodeValue is to be null and hence cannot be set. However, you can create a text node and append it to the element node. You can put the value in the text node.

### Traversing the XML Tree

#### Question

How to traverse the XML tree

#### Answer

You can traverse the tree by using the DOM API. Or alternately, you can use the selectNodes() method which takes XPath syntax to navigate through the XML document. selectNodes() is part of oracle.xml.parser.v2.XMLNode.

### Extracting Elements from XML File

#### Question

How do I extract elements from the XML file?

#### Answer

If you're using DOM, the getElementsByTagName() method can be used to get all of the elements in the document.

### Does a DTD Validate the DOM Tree?

#### Question

If I add a DTD to an XML Document, does it validate the DOM tree?

#### Answer

No, we do not do any validation while creating the DOM tree using the DOM APIs. So setting the DTD in the Document will not help in validating the DOM tree that is constructed. The only way to validate an XML file is to parse the XML document using the DOMParser or SAXParser.

### First Child Node Element Value

#### Question

How do I efficiently obtain the value of first child node of the element without going through the DOM Tree?

#### Answer

If you do not need the entire tree, use the SAX interface to return the desired data. Since it is event-driven, it does not have to parse the whole document.

### Creating DocType Node

#### Question

How do I create a DocType Node?

#### Answer

The only current way of creating a doctype node is by using the parseDTD functions. For example, emp.dtd has the following DTD:

    <!ELEMENT employee (Name, Dept, Title)>
     <!ELEMENT Name (#PCDATA)>
    <!ELEMENT Dept (#PCDATA)>
     <!ELEMENT Title (#PCDATA)>

You can use the following code to create a doctype node:

    parser.parseDTD(new FileInputStream(emp.dtd), "employee");
    dtd = parser.getDocType();

### XMLNode.selectNodes() Method

#### Question

How do I use the selectNodes() method in XMLNode class?

#### Answer

The selectNodes() method is used in XMLElement and XMLDocument nodes. This method is used to extract contents from the tree/subtree based on the select patterns allowed by XSL. The optional second parameter of selectNodes, is used to resolve Namespace prefixes (return the expanded namespace URL given a prefix). XMLElement implements NSResolver, so it can be sent as the second parameter. XMLElement resolves the prefixes based on the input document. You can implement the NSResolver interface, if you need to overide the namespace definitions. The following sample code uses selectNodes

    public class SelectNodesTest  {
    public static void main(String[] args) throws Exception {
    String pattern = "/family/member/text()";
    String file    = args[0];

    if (args.length == 2)
      pattern = args[1];

    DOMParser dp = new DOMParser();

    dp.parse(createURL(file));  // Include createURL from DOMSample
    XMLDocument xd = dp.getDocument();
    XMLElement e = (XMLElement) xd.getDocumentElement();
    NodeList nl = e.selectNodes(pattern, e);
    for (int i = 0; i < nl.getLength(); i++) {
       System.out.println(nl.item(i).getNodeValue());
        }
      }
    }

    > java SelectNodesTest family.xml
    Sarah
    Bob
    Joanne
    Jim

    > java SelectNodesTest family.xml //member/@memberid
    m1
    m2
    m3
    m4

### Using SAX API to Get the Data Value

#### Question

I am using SAX to parse an XML document. How does it get the value of the data?

#### Answer

During a SAX parse the value of an element will be the concatenation of the characters reported from after the startElement event to before the corresponding endElement event is called.

### SAXSample.java

#### Question

Inside the SAXSample program, I did not see any line that explicitly calls setDocumentLocator and some other methods. However, these methods are 'run'. Can you explain when they are called and from where

#### Answer

SAX is a standard interface for event-based XML parsing. The parser reports parsing events directly through callback functions such as setDocumentLocator() and startDocument(). The application, in this case, the SAXSample, implements handlers to deal with the different events. Here is a good place to help you start learning about the event-driven API, SAX: http://www.megginson.com/SAX/index.html

### Does DOMParser implement Parser interface

#### Question

Does the XML Parser DOMParser implement org.xml.sax.Parser interface at all ? The documentation says it implements XMLConstants and the API does not include that class at all.

#### Answer

You'll want oracle.xml.parser.v2.SAXParser to work with SAX and to have something that implements the org.xml.sax.Parser interface.

### Creating an New Document Type Node Via DOM

#### Question

I am trying to create a XML file on the fly. I use the NodeFactory to contruct a document (createDocument()). I have then setStandalone("no") and setVersion("1.0"). when I try to add a DOCTYPE node via appendChild( new XMLNode("test", Node.DOCUMENT_TYPE_NODE)), I get a ClassCastException. What is the mechanism to add a node of this type? I noticed that the NodeFactory did not have a machanism for creating a DOCTYPE node.

#### Answer

There is no mechanism to create a new DOCUMENT_TYPE_NODE object via DOM APIs. The only way to get a DTD object is to parse theDTD file or the XML file using the DOMParser, and then use the getDocType() method.

Note that new XMLNode("test",Node.DOCUMENT_TYPE_NODE) does not create a DTDobject. It creates an XMLNode object with the type set toDOCUMENT_TYPE_NODE, which infact should not be allowed. TheClassCastException is raised because appendChild expects a DTDobject (based on the type).

Also, we do not do any validation while creating the DOM tree using the DOM APIs. So setting the DTD in the Document will not help in validating the DOM tree that is constructed. The only way to validate an XML file is to parse the XML document using DOMParser or SAXParser.

### Querying for First Child Node's Value of a Certain Tag

#### Question

I am using the XML Parser for Java v2. Given a XML document containing the following Calculus Math Jim Green Jack Mary Paul, I want to obtain the value of first child node of whose tag is . I could not find any method that can do that efficiently. The nearest match is method getElementsByTag("Name"), which traverses the entire tree under .

#### Answer

Your best bet, if you do not need the entire tree, is to use the SAX interface to return the desired data. Since it is event driven it does not have to parse the whole document.

### XML Document Generation From Data in Variables

#### Question

Is there an example of XML document generation starting from information contained in simple variables? An example would be: A client fills a Java form and wants to obtain an XML document containing the given data.

#### Answer

Here are two possible interpretations of your question and answers to both. Let's say you have two variables in Java:

    String firstname = "Gianfranco";
    String lastname = "Pietraforte";

The two ways that come to mind first to get this into an XML document are as follows:

1. Make an XML document in a string and parse it.

       String xml = "<person><first>"+firstname+"</first>"+

"<last>"+lastname+"</last></person";

     DOMParser d = new DOMParser();
     d.parse( new StringReader(xml));
     Document xmldoc = d.getDocument();

- Use DOM API's to construct the document and "stitch" it together:

      Document xmldoc = new XMLDocument();
      Element e1 = xmldoc.createElement("person");
      xmldoc.appendChild(e1);
      Element e2 = xmldoc.createElement("first");
      e1.appendChild(e2);
      Text t = xmldoc.createText(firstname);
      e2.appendChild(t);
      // and so on

  ### Printing Data in the Element Tags: DOM API

  #### Question

  Can you suggest how to get a print out using the DOM API in Java:

      <name>macy</name>

  I want to print out "macy". Dont know which class and what fucntion to use. I was successful in printing "name" on to the console.

  #### Answer

  For DOM, you need to first realize that <name>macy</name> is actually an element named "name" with a child node (Text Node) of value "macy".

  So, you can do the followinig:

      String value = myElement.getFirstChild().getNodeValue();

  ### Building XML Files from Hashtable Value Pairs

  #### Question

  We have a hash table of key value pairs, how do we build an XML file out of it using the DOM API? We have a hashtablekey = valuename = georgezip = 20000. How do we build this?

      <key>value</key><name>george</name><zip>20000</zip>'

  Is there a utility to do it automatically?

  #### Answer

  1. Get the enumeration of keys from your hashtable

  2. Loop while enum.hasMoreElements()

  3. For each key in the enumeration, use the createElement() on DOM Document to create an element by the name of the key with a child text node with the value of the *value* of the hashtable entry for that key.

  ### XML Parser for Java: wrong_document_err on Node.appendChild()

  #### Question

  I have a question regarding our XML parser (v2) implementation. Say if I have the following scenario:

        Document doc1 = new XMLDocument();
        Element element1 = doc1.creatElement("foo");
        Document doc2 = new XMLDocument();
        Element element2 = doc2.createElement("bar");
        element1.appendChild(element2);

  My question is whether or not we should get a DOMException of WRONG_DOCUMENT_ERR on calling the appendChild() routine. This comes to my mind when I look at the XSLSample.java distributed with the XMLparser (v2). Any feedback would be greatly appreciated.

  #### Answer

  Yes you should get this error, since the owner document of element1 is doc1 while that of element2 is doc2. AppendChild() only works within a single tree and you are dealing with two different ones.

  #### Question 2

  In XSLSample.java that's shipped with xmlparser v2: DocumentFragment result = processor.processXSL(xsl, xml); // create an output document to hold the result out = new XMLDocument(); // create a dummy document element for the output document Element root = out.createElement("root"); out.appendChild(root); // append the transformed tree to the dummy document element root.appendChild(result);Nodes root and result are created from different XMLDocuments, wouldn't this result in the WRONG_DOCUMENT_ERR when we try to append result to root?

  #### Answer 2

  This sample is using a document fragment which does not have a root node, therefore there are not two XML documents.

  #### Question 3

  When appending a document fragment to a node, only the child nodes of the document fragment (but not the document fragment itself) is inserted. Wouldn't the parser check the owner document of these child nodes? I believe that's the behavior of the IBM xml parser.

  #### Comment

  I am experimenting the same sort of problem. From my personal point of view, a DocumentFragment shouldn't be bound to a 'root' node in any case, since, by definition, a frangment could very well be just a list of nodes ... The root node, if any, should be considered a single child. i.e. you cold for example take all the lines of an Invoice document, and add them into an ProviderOrder document, without taking the invoice itself...Don't really know if this makes sense... anyway, how do we create a documentFragment without root?, same as the XSL-T Processor does, so that we can append it to other document?

  ### Creating Nodes: DOMException when Setting Node Value

  #### Question

  I get the following error:

      oracle.xml.parser.XMLDOMException: Node cannot be modifiedwhile trying to set
      the value of a newly created node as below:     String eName="Mynode";
      XMLNode aNode = new XMLNode(eName, Node.ELEMENT_NODE);
      aNode.setNodeValue(eValue);

  How do I create a node whose value I can set later on?

  #### Answer

  Check the DOM notes where they discuss the node type. You will see that if you are creating an element node, its nodeValue is null and hence cannot be set.

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index