Java XML: ClassCastException DeferredTextImpl
Asked Answered
T

3

9

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.

Tartrazine answered 8/11, 2012 at 19:46 Comment(3)
please post your imports, think you missed something there.Lysippus
It would be helpful if you pointed out which line in your snippet is line 61.Portiaportico
Plus, the title is wrong. This is not a parsing error, but a class cast exception.Sanfordsanfourd
S
17
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.

Sanfordsanfourd answered 8/11, 2012 at 19:51 Comment(7)
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#textTartrazine
you are aware that newlines will produce text nodes inbetween of your elements? Your first node is the newline inbetween of <rule-tree> and <rule>. Which is a string of length 1, containing \n.Sanfordsanfourd
So, I'm guessing that when the #text outputs, that is the \n?Tartrazine
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.Sanfordsanfourd
What would these two lines do? dbf.setNamespaceAware(true); dbf.setValidating(dtdValidate || xsdValidate);Tartrazine
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.Sanfordsanfourd
Is there an easy way to remove those #test from the NodeList?Tartrazine
A
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

Almazan answered 8/11, 2012 at 20:1 Comment(3)
What would these two lines do? dbf.setNamespaceAware(true); dbf.setValidating(dtdValidate || xsdValidate);Tartrazine
The first one (dbf.setNamespaceAware(true);) makes the parser take XML namespaces 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.Almazan
As for the second one (dbf.setValidating(dtdValidate || xsdValidate); ), it's possible to embed Document Type Definitions in XML documents. If such definition is provided, it's possible to not only check if a document is well formed 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.Almazan
G
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);
         ............................
    }
}
Gumdrop answered 19/5, 2013 at 8:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.