org.w3c.dom.Node
is an interface. org.apache.xerces.dom.DeferredElementImpl is an implementation of that interface. It seems that DeferredElementImpl does not implement getTextContent() properly. There are a lot of other implementations. If you write a program that uses DocumentBuilderFactory, then when you run it, you will actually be using one of the implementations.
You can choose between:
- "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" Is the standard implementation bundled in the Sun JRE.
- "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl" The non-standard XML parser. Specified in a library on your classpath. That is perfectly fine, but it's something you should be aware of.
The method javax.xml.parsers.DocumentBuilderFactory#newInstance() uses the following ordered lookup procedure to determine the implementation class to load:. See Javadoc for details
- Use the javax.xml.parsers.DocumentBuilderFactory system property.
- Use the properties file "lib/jaxp.properties" in the JRE directory.
- Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for a classname in the file META-INF/services/javax.xml.parsers.DocumentBuilderFactory in jars available to the runtime.
- Platform default DocumentBuilderFactory instance.
Setting the jaxp.debug system property will cause this method to print a lot of debug messages to System.err
java -Djaxp.debug=1 YourProgram .... or java -Djaxp.debug=true YourProgram ....
The method javax.xml.parsers.DocumentBuilderFactory#newInstance(String factoryClassName, ClassLoader classLoader) specifies the implementation class to load
How to find the JAXP implementations been used
private static void OutputJaxpImplementationInfo() { System.out.println(getJaxpImplementationInfo("DocumentBuilderFactory", DocumentBuilderFactory.newInstance().getClass())); System.out.println(getJaxpImplementationInfo("XPathFactory", XPathFactory.newInstance().getClass())); System.out.println(getJaxpImplementationInfo("TransformerFactory", TransformerFactory.newInstance().getClass())); System.out.println(getJaxpImplementationInfo("SAXParserFactory", SAXParserFactory.newInstance().getClass())); System.out.println(getJaxpImplementationInfo("SchemaFactory", SchemaFactory.newInstance().getClass())); } private static String getJaxpImplementationInfo(String componentName, Class componentClass) { CodeSource source = componentClass.getProtectionDomain().getCodeSource(); return MessageFormat.format( "{0} implementation: {1} loaded from: {2}", componentName, componentClass.getName(), source == null ? "Java Runtime" : source.getLocation()); }
Possible Solutions
Update your JAXP jar implementation
- Do a mvn dependency:tree and see if there are any xerces related jars that need to be removed or updated from an implied version to declaring one that works
- Google/Bing the most recent verision of your jar library
Use the default implementation
- Given the order used to determine the implementation to load, we can set System property javax.xml.parsers.DocumentBuilderFactory System.setProperty("javax.xml.parsers.DocumentBuilderFactory","com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
- In command line add -Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
- The best solution for me is passing a parameter to DocumentBuilderFactory to specify which parser to use: DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance("com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", null);
I hope you find this information useful, and if you have aditional information or questions you can leave a comment :)