XmlResourceParser implementation - android

I need to dynamically load a xml layout from the server. LayoutInflater has inflate methods that use a XmlPullParser. I've tried that, but it doesn't work.
Looking into the Android source code, it turns out those inflate methods are called with a XmlResourceParser. The implementation Android uses is XmlBlock.Parser, but that is not a public API.
Is there a XmlResourceParser public implementation I can use?

You can use a traditional XmlPullParser like described in Android documentation :
InputStream yourRemoteLayout = ...;
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
parser.setInput(yourRemoteLayout, "someEncoding");
AttributeSet attributes = Xml.asAttributeSet(parser);
Please see what's explained in XmlPullParser documentation for more details.
Edit : From LayoutInflater#inflate() documentation :
Important For performance reasons, view inflation relies heavily on pre-processing of XML files that is done at build time. Therefore, it is not currently possible to use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
What I guess, is that maybe you should make your own implementation of LayoutInflater.Factory2 if Android's own only rely on preprocessed resources.

in fact, you CAN NOT load xml layout dynamically. android system DOES NOT need a XmlResourceParser. when android ui system inflate an resource, it just convert the parser to it's private implementation, a binary xml source parser (i forgot the class name).
1 year ago, i tried this, spent many many times. so, don't waste your time as me again.

YES, right now is possible with ItsNat Droid.
Take a look to this summary:
https://groups.google.com/forum/#!topic/itsnat/13nl0P12J_s
It is still under heavy development but most important features are already implemented.

For performance reasons, view inflation relies heavily on pre-processing of XML files that is done at build time. Therefore, it is not currently possible to use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
That isn't to say it can't be done. But you will need to run the build tools on the xml file to get it into the right format. Then you can probably mock a 'Context' and 'Resources' that returns the downloaded data when used in a 'LayoutInflator'

Related

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);

How to use external xml by XmlPullParser and LayoutInflater on Android?

I want to use external(like /storage/sdcard0/main.xml) xml as Layout by LayoutInflater.
So I found use external xml by XmlPullParser. But It didn't work!!
How to write xml source which is operating on XmlPullParser and LayoutInflater?
LayoutInflater does not work on arbitrary xml at runtime. See the comment on LayoutInflater.inflate.
Important For performance reasons, view inflation relies heavily on pre-processing of XML files that is done at build time. Therefore, it is not currently possible to use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
The platform performs a downcast in Resources.java that makes this assumption.
// XXX note that for now we only work with compiled XML files.
// To support generic XML files we will need to manually parse
// out the attributes from the XML file (applying type information
// contained in the resources and such).
XmlBlock.Parser parser = (XmlBlock.Parser)set;

How to Pull an RSS Feed using XmlPullParser in Android

I'm building an RSS reader APP, and I've been told to use the XMLPullParser interface.
Here is the block of code I'm working with:
XmlResourceParser parser = context.getResources().getXml(resource);
'Resource' is a an integer with the R.id. integer of the Xml file. This is not an internal XML file, so I don't know how to work around this.
Any ideas? Is the XmlResourceParser the wrong approach for this project? I've seen XMLReaders used with content handlers as well. Can you integrate these technologies together?
Thank you
what is the type of your xml source?
xmlPullParser can be used to parse any xml sources.
It is in my opinion the way to do this. Only problem you may encounter is when the rss feed has empty lines. The xml pullparser of android (api-level 14) jumps to the /channel if this is the case. When implementing the parser try to use the AsyncTask to start the reading of the rss feed.
Success with the implementation.

Are there any StAX implementation for android?

I want to use StAX API implementation in android 1.6 and above devices. Are there any implementations out there ? I cannot use the jar file directly since it gives issues regarding inner class. If its not available, is there any way I can recompile the implementation ? Is there an alternate way for POJO class to be mapped into XML and vice versa directly, please exclude SAX parser and DOM parser.
I think it is possible for POJO class to be mapped into XML and vice versa using JAXB. But the situation is like this. Consider this example,
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cars>
<car registration="abc123">
<brand>BMW</brand>
<description>Sedan</description>
</car>
<car registration="abc123">
<brand>Ferrari</brand>
<description>SportsCar</description>
</car>
</cars>
Now in the result I want List which has the 2 cars in it.
Also how does JAXB parser fare against StAX ?
As far as I know, both Woodstox and Aalto should work on Android. Aalto is the single fastest conforming XML parser on Java platform, if that matters; and Woodstox supports widest range of XML constructs (from full DTD handling to RelaxNG/XML Schema validation).
For binding POJOs to XML, you could also consider Jackson extension jackson-xml-databind: while Jackson is mainly JSON processor, extension supports JAXB-style data binding for XML. And does it faster than JAXB reference implementation (see jvm-serializers benchmark).
This also should work on Android (Jackson itself is nr 1 JSON parser on Android).
So what you really want to "map POJOs into the XML and vice versa" is the Simple XML Library. You can use it with every version of Android from 1.5 up.
I even wrote a blog post explaining how to include it in one of your projects.

How to encode XML on Android?

I need to encode an XML document into a format that will pass through an XML parser as a string (i.e. strip tags). I then need to decode it back again and I need to do this on Android. What is the library/class in the Android API that I'm looking for?
Thanks
XmlSerializer is probably what you want. Use it to build the "outer" XML document; you can give its text(...) method an intact XML string and it will do the escaping for you. You can do the same kind of thing with the DOM API by using setTextContent if you really want to build a DOM tree and then dump that to XML. As you appear to be aware, any XML parser will properly decode the entity references when you ask for the text back.
If you really want to write your own XML-building code, you might try pulling in the Apache commons-lang library into your project for it's StringEscapeUtils class. I'm not aware of anything that will just do the entity substitution without building real XML in the base Android API.
For an example, try this:
XmlSerializer xs = Xml.newSerializer();
StringWriter sw = new StringWriter();
xs.setOutput(sw);
xs.startDocument(null, null);
xs.startTag(null, "foo");
xs.text("<bar>this is some complete XML document you had around before</bar>");
xs.endTag(null, "foo");
xs.endDocument();
Log.v("XMLTest", "Generated XML = " + sw.toString());
I ended up using URLEncoder/URLDecoder, which seems to work nicely.
String encoded = URLEncoder.encode(xml);
The general Java XML Parser is the way to go.
and if you have to build it up manually you can use the XmlSerializer
edit:
Here is an article about working with xml on android, but It uses the XmlSerializer for the writing also
this question is one of the first results, when I searched the solution to this problem, so I answer here
Html.fromHtml(String)

Categories

Resources