7

I created a Java application which opens an xml file that looks something like this:

<AnimalTree>
  <animal>
    <mammal>canine</mammal>
    <color>blue</color>
  </animal>
  <!-- ... -->
</AnimalTree>

And I can open it using:

File fXmlFile = getResources.getXml("res/xml/data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList animalNodes = doc.getElementsByTagName("animal");

Then I can simply create a node, push the object into a ListArray, then do what I want with the objects as I loop through the ListArray.

for (int temp = 0; temp < animalNodes.getLength(); temp++) {
Node nNode = animalNodes.item(temp);     
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
question thisAnimal = new animal();
thisAnimal.mammal = getTagValue("mammal",eElement);
// ...

Plain and simple! Now only, in Android I cannot simply read the file "res/xml/data.xml" because "File();" requires a String not an integer (id). This is where I am lost. Is there some way I can make "File();" open the file, or is this impossible without using SAXparser or XPP? (both of which I really cannot understand, no matter how hard I try.)
If I am forced to use those methods, can someone show me some simple code analogous to my example?

rekire
  • 47,260
  • 30
  • 167
  • 264
jeremy
  • 145
  • 1
  • 2
  • 6

3 Answers3

9

If it's in the resource tree, it'll get an ID assigned to it, so you can open a stream to it with the openRawResource function:

InputStream is = context.getResources().openRawResource(R.xml.data);

As for working with XML in Android, this link on ibm.com is incredibly thorough.

See Listing 9. DOM-based implementation of feed parser in that link.

Once you have the input stream (above) you can pass it to an instance of DocumentBuilder:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(this.getInputStream());
Element root = dom.getDocumentElement();
NodeList items = root.getElementsByTagName("TheTagYouWant");

Keep in mind, I haven't done this personally -- I'm assuming the code provided by IBM works.

jcollum
  • 43,623
  • 55
  • 191
  • 321
  • I don't get it? Do i then change is to a string and put that into "File();" ? The IBM resource you left shows how to pull xml from online just fine. I don't understand why this is so hard? Can you create a pseudo code version of what I posted above? Thanks. – jeremy Dec 02 '10 at 15:54
  • That's better and I saw that on the IBM site, but "getInputStream();" is in the BaseFeedParser class, which "implements" the FeedParser class which is not listed on the IBM site. I created the BaseFeedParser class in my code, but eclipse is throwing an error at me about FeedParser. – jeremy Dec 02 '10 at 21:03
  • that site says : "However, DOM generally consumes more memory as everything is read into memory first. This can be a problem on mobile devices that run Android, but it can be satisfactory in certain use cases where the size of the XML document will never be very large. One might imply that the developers of Android guessed that SAX parsing would be much more common on Android applications, hence the extra utilities provided for it. " This is very bad. my XML is goind to have about 100 objects. The DOM method added 50 lines of code to my project, this is too impractical. – jeremy Dec 02 '10 at 21:31
  • 1
    Are you using XML for local storage of data? I'd recommend SQLite in that case. It's native to the stack. – jcollum Dec 02 '10 at 22:07
  • Re: FeedParser: it's an interface: `public interface FeedParser ` – jcollum Dec 02 '10 at 22:08
  • Also, there is code on there that uses inputstream via SAX, look for this: `SAXParserFactory factory = SAXParserFactory.newInstance();` – jcollum Dec 02 '10 at 22:10
  • Also note that `openRawResource(R.xml.data)` will currently give you a lint error in Android Studio: "Expected resource of type raw". Instead use `getXml()` (see BfD's answer). – LarsH Jun 12 '17 at 21:29
2

I tried the approach using openRawResource and got a SAXParseException. So, instead, I used getXml to get a XmlPullParser. Then I used next() to step through the parsing events. The actual file is res/xml/dinosaurs.xml.

XmlResourceParser parser = context.getResources().getXml(R.xml.dinosaurs);
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
    switch (eventType) {
        case XmlPullParser.START_DOCUMENT :
            Log.v(log_tag, "Start document");
            break;
        case XmlPullParser.START_TAG :
            Log.v(log_tag, "Start tag " + parser.getName() );
            break;
        case XmlPullParser.END_TAG :
            Log.v(log_tag, "End tag " + parser.getName() );
            break;
        case XmlPullParser.TEXT :
            Log.v(log_tag, "Text " + parser.getText() );
            break;
        default :
            Log.e(log_tag, "Unexpected eventType = " + eventType );
    }
    eventType = parser.next();
}
BfD
  • 21
  • 2
-1

Try this,

this.getResources().getString(R.xml.test); // returns you the path , in string,invoked on activity object
Abhiram mishra
  • 1,597
  • 2
  • 14
  • 34