简体   繁体   中英

How can I specify which XML parser implementation to use?

I am currently trying to write an app (a game) that will, I hope, run on both desktop and Android. The data format I have chosen to use is XML because it's more flexible and powerful than JSON, it performs better than a database and I am familiar with it and like it.

However, I'm beginning to wonder if it's going to actually be possible to use XML.

In addition to plain old XML I'm also using XInclude in my data structures and XPath to locate the relevant nodes. This seems to require that I also validate my XML during parse, which is fine because I had already written the XML Schema when developing the XML in the first place.

I've managed to get everything working on the desktop, however, as soon as I tried to run it on Android it failed. It seems that the XML parser used by default on Android doesn't support XInclude ( source ).

I've added the following line to my build.gradle:

compile "xerces:xercesImpl:2.12.0"

and it seems to have worked in that the SchemaFactory seems to be resolving to the Xerces one as evidenced by the debugging output:

08-21 14:19:35.488 8254-8332 W/System.err: JAXP: Reading jar:file:/data/app/uk.co.redfruit.gdx.wobbegong-geDT8AfzN-vHBlDA-lE0_g==/base.apk!/META-INF/services/javax.xml.validation.SchemaFactory
    JAXP: instantiating org.apache.xerces.jaxp.validation.XMLSchemaFactory

But the DocumentBuilderFactory appears to be using the default Android one because it still throws the error:

java.lang.UnsupportedOperationException: This parser does not support specification "Unknown" version "0.0"

Which is what is always thrown when you call setXIncludeAware on the DocumentBuilderFactory (See above link).

I had assumed that including it in my gradle build file would do the trick and it seems like it partly has, but not enough.

I'm hoping that all crosss platform XML parsing problems will be solved by using the same parser implementation on all platforms, but it doesn't seem as straight forward as that...

Take a look at the javadocs for DocumentBuilderFactory.newInstance()

Use the javax.xml.parsers.DocumentBuilderFactory system property.

I suggest you set the javax.xml.parsers.DocumentBuilderFactory system property to the classname of the xerces DocumentBuilderFactory implementation

I'm guessing it's this is the class you want

eg:

System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
doFunkyXmlStuff();

To specify the parser to be used as Xerces-2, I would suggest to pass the parser classname when instantiating the DocumentBuilderFactory as follows:

DocumentBuilderFactory docFactory = DocumentBuilderFactory
        .newInstance("org.apache.xerces.jaxp.DocumentBuilderFactoryImpl", null);
docFactory.setXIncludeAware(true);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM