Using SAXparser to get info to more than one element (Android)

耗尽温柔 提交于 2019-12-30 13:15:07

问题


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

    }


回答1:


Problem solved!

Bellow are the sites with useful information:

  • https://stackoverflow.com/a/4828765
  • https://stackoverflow.com/a/5709544
  • http://as400samplecode.blogspot.com/2011/11/android-parse-xml-file-example-using.html
  • http://www.anddev.org/novice-tutorials-f8/parsing-xml-from-the-net-using-the-saxparser-t353.html

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...



来源:https://stackoverflow.com/questions/9244345/using-saxparser-to-get-info-to-more-than-one-element-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!