1

I'm new in Android (and in Java too) but now I'm starting to work with web services.

So to understand better how to parse an XML, I started to try this tutorial:

http://www.anddev.org/novice-tutorials-f8/parsing-xml-from-the-net-using-the-saxparser-t353.html

With the XML used in this example:

<outertag>
<innertag sampleattribute="innertagAttribute">
<mytag>anddev.org rulez =)</mytag>
<tagwithnumber thenumber="1337"/>
</innertag>
</outertag>

I understand how it works (I guess), but if the XML is like this:

<outertag>
<innertag sampleattribute="innertagAttribute">
<mytag>anddev.org rulez =)</mytag>
<tagwithnumber thenumber="1337"/>
</innertag>
<innertag sampleattribute="innertagAttribute2">
<mytag>something</mytag>
<tagwithnumber thenumber="14214"/>
</innertag>
</outertag>

What needs to change in the classes of the application to obtain the data of the various elements?

I appreciate any sugestion...

Full source code:

  • ParseXML.java

    package org.anddev.android.parsingxml;

    import java.net.URL;

    import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory;

    import org.xml.sax.InputSource; import org.xml.sax.XMLReader;

    import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.TextView;

    public class ParsingXML extends Activity {

    private final String MY_DEBUG_TAG = "WeatherForcaster";
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
    
        /* Create a new TextView to display the parsingresult later. */
        TextView tv = new TextView(this);
        try {
            /* Create a URL we want to load some xml-data from. */
            URL url = new URL("http://www.anddev.org/images/tut/basic/parsingxml/example.xml");
    
            /* Get a SAXParser from the SAXPArserFactory. */
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();
    
            /* Get the XMLReader of the SAXParser we created. */
            XMLReader xr = sp.getXMLReader();
            /* Create a new ContentHandler and apply it to the XML-Reader*/ 
            ExampleHandler myExampleHandler = new ExampleHandler();
            xr.setContentHandler(myExampleHandler);
    
            /* Parse the xml-data from our URL. */
            xr.parse(new InputSource(url.openStream()));
            /* Parsing has finished. */
    
            /* Our ExampleHandler now provides the parsed data to us. */
            ParsedExampleDataSet parsedExampleDataSet = 
                                    myExampleHandler.getParsedData();
    
            /* Set the result to be displayed in our GUI. */
            tv.setText(parsedExampleDataSet.toString());
    
        } catch (Exception e) {
            /* Display any Error to the GUI. */
            tv.setText("Error: " + e.getMessage());
            Log.e(MY_DEBUG_TAG, "WeatherQueryError", e);
        }
        /* Display the TextView. */
        this.setContentView(tv);
    }
    

    }

  • ExampleHandler

    package org.anddev.android.parsingxml;

    import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler;

    public class ExampleHandler extends DefaultHandler{

    // ===========================================================
    // Fields
    // ===========================================================
    
    private boolean in_outertag = false;
    private boolean in_innertag = false;
    private boolean in_mytag = false;
    
    private ParsedExampleDataSet myParsedExampleDataSet = new ParsedExampleDataSet();
    
    // ===========================================================
    // Getter & Setter
    // ===========================================================
    
    public ParsedExampleDataSet getParsedData() {
        return this.myParsedExampleDataSet;
    }
    
    // ===========================================================
    // Methods
    // ===========================================================
    @Override
    public void startDocument() throws SAXException {
        this.myParsedExampleDataSet = new ParsedExampleDataSet();
    }
    
    @Override
    public void endDocument() throws SAXException {
        // Nothing to do
    }
    
    /** Gets be called on opening tags like: 
     * <tag> 
     * Can provide attribute(s), when xml was like:
     * <tag attribute="attributeValue">*/
    @Override
    public void startElement(String namespaceURI, String localName,
            String qName, Attributes atts) throws SAXException {
        if (localName.equals("outertag")) {
            this.in_outertag = true;
        }else if (localName.equals("innertag")) {
            this.in_innertag = true;
        }else if (localName.equals("mytag")) {
            this.in_mytag = true;
        }else if (localName.equals("tagwithnumber")) {
            // Extract an Attribute
            String attrValue = atts.getValue("thenumber");
            int i = Integer.parseInt(attrValue);
            myParsedExampleDataSet.setExtractedInt(i);
        }
    }
    
    /** Gets be called on closing tags like: 
     * </tag> */
    @Override
    public void endElement(String namespaceURI, String localName, String qName)
            throws SAXException {
        if (localName.equals("outertag")) {
            this.in_outertag = false;
        }else if (localName.equals("innertag")) {
            this.in_innertag = false;
        }else if (localName.equals("mytag")) {
            this.in_mytag = false;
        }else if (localName.equals("tagwithnumber")) {
            // Nothing to do here
        }
    }
    
    /** Gets be called on the following structure: 
     * <tag>characters</tag> */
    @Override
    public void characters(char ch[], int start, int length) {
        if(this.in_mytag){
            myParsedExampleDataSet.setExtractedString(new String(ch, start, length));
        }
    }
    

    }

  • ParsedExampleDataSet

    package org.anddev.android.parsingxml;

    public class ParsedExampleDataSet { private String extractedString = null; private int extractedInt = 0;

    public String getExtractedString() {
        return extractedString;
    }
    public void setExtractedString(String extractedString) {
        this.extractedString = extractedString;
    }
    
    public int getExtractedInt() {
        return extractedInt;
    }
    public void setExtractedInt(int extractedInt) {
        this.extractedInt = extractedInt;
    }
    
    public String toString(){
        return "ExtractedString = " + this.extractedString
                + "nExtractedInt = " + this.extractedInt;
    }
    

    }

amp
  • 11,754
  • 18
  • 77
  • 133

1 Answers1

2

Problem solved!

Bellow are the sites with useful information:

My initial problem was how I should define the class for the data which I wanted to extract from XML. After I figured out how I should do this (reviewing the basic concepts of JAVA programming), I changed the type of data returned by the ExampleHandler to an ArrayList<"class of the data you want return">.

I give below an example:

  • Example of a XML you want to parse:

    <outertag>
    <cartag type="Audi">
        <itemtag name="model">A4</itemtag>
        <itemtag name="color">Black</itemtag>
        <itemtag name="year">2005</itemtag>
    </cartag>
    <cartag type="Honda">
        <itemtag name="model">Civic</itemtag>
        <itemtag name="color">Red</itemtag>
        <itemtag name="year">2001</itemtag>
     </cartag>
     <cartag type="Seat">
        <itemtag name="model">Leon</itemtag>
        <itemtag name="color">White</itemtag>
        <itemtag name="year">2009</itemtag>
     </cartag>
     </outertag>
    

So here you should define a class "car" with proper attributes (String type, model, color, year;), setters and getters...

  • My suggestion of ExampleHandler for this XML is:

public class ExampleHandler extends DefaultHandler{

// ===========================================================
// Fields
// ===========================================================

private int numberOfItems=3;    
private boolean in_outertag = false;
private boolean in_cartag = false;
private boolean[] in_itemtag = new boolean[numberOfItems];

Car newCar = new Car(); 

private ArrayList<Car> list = new ArrayList<Car>(); 

// ===========================================================
// Getter & Setter
// ===========================================================

public ArrayList<Car> getParsedData() {
    return this.list;
}

// ===========================================================
// Methods
// ===========================================================
@Override
public void startDocument() throws SAXException {
    this.list = new ArrayList<Car>();
}

@Override
public void endDocument() throws SAXException {
    // Nothing to do
}

/** Gets be called on opening tags like: 
 * <tag> 
 * Can provide attribute(s), when xml was like:
 * <tag attribute="attributeValue">*/
@Override
public void startElement(String namespaceURI, String localName,
        String qName, Attributes atts) throws SAXException {
    if (localName.equals("outertag")) {
        this.in_outertag = true;
    }else if (localName.equals("cartag")) {
        this.in_cartag = true;
        newCar.setType(atts.getValue("type"));  //setType(...) is the setter defined in car class
    }else if (localName.equals("itemtag")) {
        if((atts.getValue("name")).equals("model")){
            this.in_itemtag[0] = true;
        }else if((atts.getValue("name")).equals("color")){
            this.in_itemtag[1] = true;
        }else if((atts.getValue("name")).equals("year")){
            this.in_itemtag[2] = true;
        }
    }
}

/** Gets be called on closing tags like: 
 * </tag> */
@Override
public void endElement(String namespaceURI, String localName, String qName)
        throws SAXException {
    if (localName.equals("outertag")) {
        this.in_outertag = false;
    }else if (localName.equals("cartag")) {
        this.in_cartag = false;
        Car carTemp = new Car();
        carTemp.copy(newCar, carTemp);  //this method is defined on car class, and is used to copy the
                                        //properties of the car to another Object car to be added to the list
        list.add(carTemp);
    }else if (localName.equals("itemtag")){
        if(in_itemtag[0]){
            this.in_itemtag[0] = false;
        }else if(in_itemtag[1]){
            this.in_itemtag[1] = false;
        }else if(in_itemtag[2]){
            this.in_itemtag[2] = false;
        }
    }
}

/** Gets be called on the following structure: 
 * <tag>characters</tag> */
@Override
public void characters(char ch[], int start, int length) {

    if(in_itemtag[0]){
        newCar.setModel(new String(ch, start, length));
    }else if(in_itemtag[1]){
        newCar.setColor(new String(ch, start, length));
    }else if(in_itemtag[2]){
        newCar.setYear(new String(ch, start, length));
    }
}

}

After this, you can get the parsed data in the Activity using:

...
ArrayList<Car> ParsedData = myExampleHandler.getParsedData();
...

I hope this helps someone.

Attention: I don't have tested exactly like this, but is almost the same of my solution so it should work...

And sorry for my bad English...

Community
  • 1
  • 1
amp
  • 11,754
  • 18
  • 77
  • 133
  • 1
    Welcome to Stack Overflow! You shouldn't just give a link to another site as an answer, since the site may go out of date in the future. Instead, click the "edit" link on this answer and include the essential parts of the solution from that page here. See: http://meta.stackexchange.com/q/8259 – Peter O. Feb 13 '12 at 02:15