8

Here is my code:

// get the factory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

try {

    // Using factory get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();

// parse using builder to get DOM representation of the XML file
    dom = db.parse(file);

} catch (ParserConfigurationException pce) {
    pce.printStackTrace();
} catch (SAXException se) {
    se.printStackTrace();
} catch (IOException ioe) {
    ioe.printStackTrace();
}

NodeList n1 = dom.getChildNodes();
Element e1 = (Element) n1.item(0);

System.out.println(n1.getLength());
System.out.println(e1.getNodeName());

NodeList n2 = n1.item(0).getChildNodes();
Element e2 = (Element) n2.item(0);   //Line 61

System.out.println(n2.getLength());
System.out.println(e2.getNodeName());

Here is my XML file:

<?xml version="1.0" encoding="utf-8"?>

<test-fw:test
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:test-fw="http://simitar/test-fw"> 

<rule-tree>
<rule class="matchlines">
<property name="contiguous"> true</property>
<property name="inOrder">false</property>
<property name="exact">false</property>
<property name="lines">modelInstantiated</property>
</rule>
<rule class="matchlines">
<property name="contiguous"> true</property>
<property name="inOrder">true</property>
<property name="exact">false</property>
<property name="lines">InitEvent</property>
</rule>
</rule-tree>

</test-fw:test>

Here is my output:

1
test-fw:test
Exception in thread "main" java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DeferredTextImpl cannot be cast to org.w3c.dom.Element
    at testpack.Main.run(Main.java:61)
    at testpack.Main.main(Main.java:86)

I keep getting this error. I am completely lost. I have no idea what to do. I want to able to have one node, and be able to grab all it's children and put them into an array or list, so I can iterate through them.

Here are all my imports:

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Stack;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

I've had the hardest time trying to get this Java to parse this XML file.

Has QUIT--Anony-Mousse
  • 76,138
  • 12
  • 138
  • 194
Rob Avery IV
  • 3,562
  • 10
  • 48
  • 72

3 Answers3

16
NodeList n1 = dom.getChildNodes();
Element e1 = (Element) n1.item(0);

The node is not an Element, but a Node.

Try this:

Node no1 = (Node) n1.item(0);

Nodes can be text nodes or elements, for example. In particular,

<root>
<element/>
</root>

is 4 nodes. A root element, a text node containing \n, the element element and another text node containing \n.

Has QUIT--Anony-Mousse
  • 76,138
  • 12
  • 138
  • 194
  • I change the Elements to Nodes, but its still gives me the wrong answer. Instead, of the Exceptions, it will output this: 1\ntest-fw:test\n3\n#text – Rob Avery IV Nov 08 '12 at 19:55
  • you are aware that newlines will produce text nodes inbetween of your elements? Your first node is the **newline** inbetween of `` and ``. Which is a string of length 1, containing `\n`. – Has QUIT--Anony-Mousse Nov 08 '12 at 19:56
  • So, I'm guessing that when the #text outputs, that is the \n? – Rob Avery IV Nov 08 '12 at 20:03
  • Yes, it is. When handling XML, make sure to program defensively against additional text nodes, and additional white space. In many cases, you may want to treat a string such as `an\n example` the same way as `an example`, to allow the user to insert arbitrary newlines to make the XML more readable. Web browsers for example do this. – Has QUIT--Anony-Mousse Nov 08 '12 at 20:06
  • What would these two lines do? dbf.setNamespaceAware(true); dbf.setValidating(dtdValidate || xsdValidate); – Rob Avery IV Nov 08 '12 at 20:16
  • Enable namespace awareness and validation. Grab a random XML book for what namespaces are (tags and attributes starting with `something:` use namespaces), and validation, well, will report errors when the file is not valid XML. – Has QUIT--Anony-Mousse Nov 08 '12 at 20:20
  • Is there an easy way to remove those #test from the NodeList? – Rob Avery IV Nov 08 '12 at 20:31
4

Notice that NodeList.itemreturns a Node object, which can but does not have to be an Element.

In your case, the method returns a DeferredTextImpl instance, which represents a text node. This class implements the DeferredNode interface, which is, in turn, a subinterface of Node.

In order to process the Node instances, you'll have to make sure you can safely perform the cast. The Node interface provides methods that allow you to check the type of a node getNodeType, which returns a short value that you can compare to the constants defined in the very same interface like ELEMENT_NODE

toniedzwiedz
  • 17,895
  • 9
  • 86
  • 131
  • What would these two lines do? dbf.setNamespaceAware(true); dbf.setValidating(dtdValidate || xsdValidate); – Rob Avery IV Nov 08 '12 at 20:15
  • The first one (`dbf.setNamespaceAware(true);`) makes the parser take [XML namespaces](http://en.wikipedia.org/wiki/XML_namespace) into consideration. To put it simply, namespaces allow you to differentiate elements with the same names and different definitions. A `cat` element can mean totally different things in a document describing animals and in a document about shell commands. Thanks to namespaces, everyone can define their own elements, structure and name them as they please. – toniedzwiedz Nov 08 '12 at 20:39
  • As for the second one (`dbf.setValidating(dtdValidate || xsdValidate);` ), it's possible to embed [Document Type Definitions](http://en.wikipedia.org/wiki/Document_Type_Definition) in XML documents. If such definition is provided, it's possible to not only check if a document is [well formed](http://en.wikipedia.org/wiki/Well-formed_element) but also follows a specific schema. Setting the `validating` property to `true` makes the parser check for compliance with an embedded DTD (if present) and not only for well-formedness. – toniedzwiedz Nov 08 '12 at 20:42
4

Just need to check the Nodeis an Element or not . Following is the way to convert Node into Element.

NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
    if(nodes.item(i).getNodeType() == Node.ELEMENT_NODE){
         Element element = (Element) nodes.item(i);
         ............................
    }
}
Community
  • 1
  • 1
Harmeet Singh Taara
  • 6,483
  • 20
  • 73
  • 126