-->

Get org.w3c.dom.Document from XMLResourceParser

2019-09-12 02:02发布

问题:

I'm planning on putting some XML files in my res/xml directory, which I want to load into Document objects (as I'm using these currently in my application and am passing them around a lot).

Doing:

XMLResourceParser parser = getResources().getXml(R.xml.my_xml_file)

seems to be the only starting point and the XMLResourceParser implements XmlPullParser, which seems to be aimed at iterating through the tree of nodes.

I've tried using xpath to pull out the root node of the document, as per the code in this answer: navigate through XML document with XMLpullParser, but this gives me an exception as per this question: Evaluating XPath an XmlResourceParser causes Exception

Ideally, I need to keep the xml in the res/xml folder, as I'll want to localise the content, so moving it to res/raw or res/assets isn't an option.

Before I implement something which iterates through the XmlResourceParser and builds the Document, is there a simpler way of doing this?

回答1:

Writing the code to iterate through the XMLResourceParser shows that you are a nice well-mannered developer.

However, you may be tempted to use the evil genius option.

First, create an XmlPullParser implementation that takes an XmlResourceParser in the constructor, wraps it and delegates all its methods to it -- except all the setInput-type methods. You want all those to be no-op stubs, because XmlResourceParser will throw exceptions (see XmlBlock.java, line 108 or so). Android studio can automate creating the delegate methods so you don't have to hand-code all that.

    PullParserWrapper wrapper = new PullParserWrapper(
            getResources().getXml(R.xml.my_xml_file));

Note: Your wrapper class might have to have some method implementations to handle turning off namespace processing and other assorted things.

Next, you will use a org.xmlpull.v1.sax2.Driver to wrap your parser and convert it into an XMLReader:

    XMLReader xmlReader = new Driver(wrapper);

Now set up a dummy input source (the XmlResourceParser already knows where it's getting its input):

    InputSource inputSource = new InputSource(new StringReader(""));

Then you use a Transformer to convert your SAX input to a DOM output and get your result:

        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        DOMResult domResult = new DOMResult();
        transformer.transform(new SAXSource(xmlReader, inputSource), domResult);
        Document document = (Document) domResult.getNode();

MWAH Ha Ha Ha Ha Ha Ha!