Android XML + Object Storage
Question: I am sorry if this is a simple fix (I'm sure it probably is) but after a few
hours of me and my friend google, I came up empty.

I have an XML file that I have retrieved from a server (using httpclient for
cookie handling goodness). I now wish to search through the XML. The XML
defines a set of playing cards with attributes. As an example it would be
something like this.

    
    
    <CardInfo>
         <Type>
               Player
         </Type>
         <ID>
               674868
        </ID>
    </CardInfo>
    

There would obviously be a few more attributes within this, but that is to
just illustrate the example. There may be many of these 'cardinfo' per XML I
pull, I would like some way of filtering the XML to store each card, and have
the attributes of the card in an easy to access form. I obviously do not
expect all of this done for me, but thought the context may be important for
any solutions.

I'm sorry to ask this, and feel terrible for doing so, but even XML parsing
and storage is difficult for an android nooby! (why can't they let us do it in
python for the love of god).


Answer: Use an [XML pull-
parser](http://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html).
It gives you the XML document is its logical pieces, part (event) per part. So
for each CardInfo element, you create a new CardInto object, and for element
name 'Type' you set the CardInfo type and for element name 'ID' you set the
CardInfo type etc.

**Update** Add read and write methods to your objects, or create a standalone
class for read/write to and from XML:

This example is for the StAX API, but I guess you get the picture (the methods
and event types are the same, but have difference names).

In MyObject:

    
    
    public void read(XMLStreamReader reader) throws XMLStreamException {
        int event; 
    
        // read to the first tag, so we are at level 1
        do {
            event = reader.next();
            if(event == XMLStreamConstants.START_ELEMENT) {
                break;
            }
    
        } while(reader.hasNext());
    
        int level = 1;
        do {
            event = reader.next();
            if(event == XMLStreamConstants.START_ELEMENT) {
                level++; // increment
    
                String localName = reader.getLocalName();
    
                if(localName.equals("Domain")) {
                    event = reader.next();
                    if(event == XMLStreamConstants.CHARACTERS) {
                        domain = reader.getText();
                    }
                } else if(localName.equals("URL")) {
                    event = reader.next();
                    if(event == XMLStreamConstants.CHARACTERS) {
                        url = reader.getText();
                    }
                } else if(localName.equals("Headers")) {
                    readHeaders(reader);
                    level--;
                } else throw new IllegalArgumentException("Unexpected element " + localName + " at " + reader.getLocation());
            }
    
    
            if(event == XMLStreamConstants.END_ELEMENT) { 
                level--; // decrement
            }
        } while(level > 0); // simple level check
    
    
    }
    

Parse the subtype called headers:

    
    
    <Headers>
        <Header name="" value=""/>
        <Header name="" value=""/>
        <Header name="" value=""/>
    </Headers>
    

using the code

    
    
    private void readHeaders(XMLStreamReader reader) throws XMLStreamException {
        int level = 1;
    
        int event;
        do {
            event = reader.next();
            if(event == XMLStreamConstants.START_ELEMENT) {
                level++;
    
                String localName = reader.getLocalName();
    
                if(localName.equals("Header")) {
                    CodeRequestHeader header = new CodeRequestHeader();
                    header.setName(reader.getAttributeValue(null, "name"));
                    header.setValue(reader.getAttributeValue(null, "value"));
                    headers.add(header);
                }
            } else if(event == XMLStreamConstants.END_ELEMENT) {
                level--;
            }
        } while(level > 0);
    }
    

Now there are multiple ways of doing this stuff, but the important things are
these:

  1. First go to level 1; read the root element
  2. Start a do-while loop at level 1
  3. Increment and decrement level on start and end elements so the level is correct
  4. Use the level to control the while loop, continue as long as level > 0
  5. For subelements (i.e. when some tag contains multiple tags which are mapped to object entities), create a new method repeating steps 2-4. Then decrement level by one when the method is used.

If you use this pattern, you can pull-parse n-dimensional XML documents in an
orderly and strict, proper way. Strictly speaking, the rules means that should
be a 'readHeader' method in the readHeaders method, but it is not necessary if
there are no subelements in the Header element. Have fun ;)

