Android programming Parsing XML Method details (Sax,dom and pull) _android

Source: Internet
Author: User
Tags getmessage gettext

This example describes the Android programming parsing XML method. Share to everyone for your reference, specific as follows:

XML is widely used in all kinds of development, and Android is no exception. As an important role in hosting data, how to read and write XML becomes an important skill in Android development. Today I'd like to introduce you to several common XML parsing and creation methods under the Android platform.

In Android, the common XML parsers are sax parsers, Dom parsers, and pull parsers, which I'll explain in more detail.

SAX parser:

The SAX (simple API for XML) parser is an event-based parser, and its core is the event-handling pattern, which revolves around the event source and the event handler. When an event source generates an event, a handler for the event handler is invoked, and an event can be processed. When the event source invokes a particular method in the event handler, it is also passed to the event handler's state information, so that the event handler can determine its behavior based on the event information provided.

The advantage of the SAX parser is that it has a fast parsing speed and consumes less memory. Ideal for use in Android mobile devices.

DOM Parser:

A DOM is a collection of nodes or pieces of information based on a tree structure that allows developers to traverse an XML tree and retrieve the required data using the DOM API. Parsing the structure usually requires loading the entire document and constructing the tree structure before you can retrieve and update node information.

Because the DOM is stored in memory in a tree structure, retrieval and update efficiency is higher. However, for exceptionally large documents, parsing and loading the entire document will be very resource intensive.

Pull parser:

The pull parser runs the same way as sax, and is an event-based pattern. The difference is that in the pull parsing process, we need to get the resulting event and then do the appropriate action, instead of executing our code by the way that the processor triggers an event like sax. The pull parser is compact, lightweight, fast, and easy to use, and is ideal for Android mobile devices, and the internal Android system uses pull parsers to parse various XML.

The above three kinds of parsers, are very useful parsers, I will be introduced. We will use these three parsing techniques to accomplish a common task.

We create a new project with the following project structure:

I will place an XML document books.xml in the assets directory of the project, as follows:

<?xml version= "1.0" encoding= "Utf-8"?>
<books>
  <book>
    <id>1001</id>
    <name>thinking in java</name>
    <price>80.00</price>
  </book>
  < book>
    <id>1002</id>
    <name>core java</name>
    <price>90.00</price >
  </book>
  <book>
    <id>1003</id>
    <name>hello, andriod</ name>
    <price>100.00</price>
  </book>
</books>

Then we use the above three kinds of parsing technology to parse the document, get a List<book> object, first look at the Book.java code:

Package Com.scott.xml.model;
public class Book {
  private int id;
  private String name;
  private float price;
  public int getId () {return
    ID;
  }
  public void setId (int id) {
    this.id = ID;
  }
  Public String GetName () {return
    name;
  }
  public void SetName (String name) {
    this.name = name;
  }
  public float GetPrice () {return price
    ;
  }
  public void Setprice (float price) {
    This.price = Price;
  }
  @Override public
  String toString () {return
    "ID: + ID +", Name: "+ name +", Price: "+ Price;
  }
}

Finally, we want to generate a new XML document for the data in this collection object, as shown in the figure:

The resulting XML structure is slightly different from the original document and is the following format:

<?xml version= "1.0" encoding= "UTF-8"?>
<books>
 <book id= "1001" >
  <name> Thinking in java</name>
  <price>80.0</price>
 </book>
 <book id= "1002" >
  <name>core java</name>
  <price>90.0</price>
 </book>
 <book id= " 1003 ">
  <name>hello, andriod</name>
  <price>100.0</price>
 </book>
</books>

Next, for the introduction of the procedure, we first define a Bookparser interface for the parser, each type of parser needs to implement this interface. The Bookparser.java code is as follows:

Package com.scott.xml.parser;
Import Java.io.InputStream;
Import java.util.List;
Import Com.scott.xml.model.Book;
Public interface Bookparser {
  /**
   * Parse input stream gets the book object collection
   * @param is
   * @return
   * @throws Exception
   * * Public
  list<book> Parse (InputStream is) throws Exception;
  /**
   * Serialization Book object collection get XML form string
   * @param books
   * @return
   * @throws Exception
  /Public String Serialize (List<book> books) throws Exception;


Well, we're going to implement the interface one by one to complete our parsing process.

Using the SAX parser:

The Saxbookparser.java code is as follows:

Package com.scott.xml.parser;
Import Java.io.InputStream;
Import Java.io.StringWriter;
Import java.util.ArrayList;
Import java.util.List;
Import Javax.xml.parsers.SAXParser;
Import Javax.xml.parsers.SAXParserFactory;
Import Javax.xml.transform.OutputKeys;
Import Javax.xml.transform.Result;
Import Javax.xml.transform.Transformer;
Import Javax.xml.transform.TransformerFactory;
Import Javax.xml.transform.sax.SAXTransformerFactory;
Import Javax.xml.transform.sax.TransformerHandler;
Import Javax.xml.transform.stream.StreamResult;
Import org.xml.sax.Attributes;
Import org.xml.sax.SAXException;
Import Org.xml.sax.helpers.AttributesImpl;
Import Org.xml.sax.helpers.DefaultHandler;
Import Com.scott.xml.model.Book; public class Saxbookparser implements Bookparser {@Override public list<book> parse (InputStream is) throws ption {SAXParserFactory factory = Saxparserfactory.newinstance ();//Get saxparserfactory instance saxparser parser = facto Ry.newsaxparser (); From factory to obtain SAXParser realExample MyHandler handler = new MyHandler (); Instantiate a custom handler Parser.parse (is, handler);
  Resolves the input stream return Handler.getbooks () according to the custom handler rule; @Override public String Serialize (List<book> books) throws Exception {Saxtransformerfactory factory = (SA xtransformerfactory) Transformerfactory.newinstance ()//Get Saxtransformerfactory instance Transformerhandler handler =      Factory.newtransformerhandler ();           Obtain Transformerhandler instance from factory Transformer Transformer = Handler.gettransformer ();      Obtain transformer instance Transformer.setoutputproperty from handler (outputkeys.encoding, "UTF-8");        Set the encoding mode of the output Transformer.setoutputproperty (outputkeys.indent, "yes");  Whether to automatically add extra blank Transformer.setoutputproperty (outputkeys.omit_xml_declaration, "no");
    Whether to ignore the XML declaration StringWriter writer = new StringWriter ();
    Result result = new Streamresult (writer);
    Handler.setresult (result);  String uri = ""; The URI that represents the namespace must be set to an empty string localname = "" When the URI has no value;
    The local name of the namespace (without the prefix) must be placed as an empty string handler.startdocument () when no namespace processing is done;
    Handler.startelement (URI, LocalName, "books", null);  Attributesimpl attrs = new Attributesimpl ();
    Responsible for storing the attribute information of the element char[] ch = null; for (book book:books) {attrs.clear ();//Empty Property list Attrs.addattribute (URI, LocalName, "id", "string", String.va  Lueof (Book.getid ());//Add a property named ID (type does not affect very much, set here as String) Handler.startelement (URI, LocalName, "book", Attrs); Start a book element to associate the id attribute handler.startelement (URI, LocalName, "name", null) set above;
      Start a name element has no attributes ch = string.valueof (Book.getname ()). ToCharArray ();  Handler.characters (CH, 0, ch.length);
      Sets the text node Handler.endelement (URI, LocalName, "name") of the name element; Handler.startelement (URI, LocalName, "price", null);/start a price element has no attributes ch = string.valueof (Book.getprice ()). Tocharar
      Ray ();  Handler.characters (CH, 0, ch.length);
      Sets the text node Handler.endelement (URI, LocalName, "price") of the price element; Handler.endelement (UrI, LocalName, "book");
    } handler.endelement (URI, LocalName, "books");
    Handler.enddocument ();
  return writer.tostring ();
    ///need to rewrite the DefaultHandler method private class MyHandler extends DefaultHandler {private list<book> books;
    Private book book;
    Private StringBuilder Builder;
    Returns the collection of book objects that are parsed public list<book> getbooks () {return books;
      @Override public void Startdocument () throws Saxexception {super.startdocument ();
      Books = new Arraylist<book> ();
    Builder = new StringBuilder (); @Override public void Startelement (string uri, String localname, String qName, Attributes Attributes) throws SAX
      Exception {super.startelement (URI, LocalName, qName, attributes);
      if (Localname.equals ("book")) {book = new book ();  } builder.setlength (0); Set the character length to 0 to restart the character node in the read element @Override public void characters (char[] ch, int start, int length) throws Saxexception {super.characters (ch, start, length); Builder.append (CH, start, length); Appends a read character array to builder @Override public void EndElement (string uri, String localname, String qName) throws SA
      xexception {super.endelement (URI, LocalName, QName);
      if (Localname.equals ("id")) {Book.setid (Integer.parseint (builder.tostring ()));
      else if (localname.equals ("name")) {Book.setname (builder.tostring ());
      else if (localname.equals ("price")) {Book.setprice (Float.parsefloat (builder.tostring));
      else if (localname.equals ("book")) {books.add (book);

 }
    }
  }
}

In the code, we define our own event-handling logic and rewrite several important event methods for DefaultHandler. Here I will highlight the defaulthandler of the relevant knowledge. DefaultHandler is an event handler that can receive all the events reported by the parser and process the data found. It implements the Entityresolver interface, the Dtdhandler interface, the ErrorHandler interface and the ContentHandler interface. These interfaces represent different types of event handlers. Let's highlight the ContentHandler interface. Structure as shown:

These more important methods have been labeled by me in red lines, DefaultHandler implement these methods, but do not do anything in the body of the method, so we must overwrite the relevant method when we use it. The most important is the Startelement method, the characters method and the EndElement method. When the start node is encountered when the document is executed, the Startelement method is invoked, we can get the information about the starting node, then the characters method is invoked, we can get the text information in the node, and the last EndElement method is called, We can do the closure of the related operation.

Finally, we need to invoke the SAX parser, which is done in mainactivity:

Package com.scott.xml;
Import Java.io.FileOutputStream;
Import Java.io.InputStream;
Import java.util.List;
Import android.app.Activity;
Import Android.content.Context;
Import Android.os.Bundle;
Import Android.util.Log;
Import Android.view.View;
Import Android.widget.Button;
Import Com.scott.xml.model.Book;
Import Com.scott.xml.parser.BookParser;
Import Com.scott.xml.parser.SaxBookParser;
  public class Mainactivity extends activity {private static final String TAG = "XML";
  Private Bookparser parser;
  Private list<book> Books;
    @Override public void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
    Setcontentview (R.layout.main);
    Button readbtn = (button) Findviewbyid (R.ID.READBTN);
    Button writebtn = (button) Findviewbyid (R.ID.WRITEBTN);
          Readbtn.setonclicklistener (New View.onclicklistener () {@Override public void OnClick (View v) {try {
          InputStream is = Getassets (). Open ("books.xml"); Parser = new Saxbookparser (); Create Saxbookparser Instance books = Parser.parse (IS);
          Parse input stream for (book book:books) {log.i (TAG, book.tostring ());
        The catch (Exception e) {log.e (TAG, E.getmessage ());
    }
      }
    }); 
          Writebtn.setonclicklistener (New View.onclicklistener () {@Override public void OnClick (View v) {try { String XML = parser.serialize (books);
          Serialized FileOutputStream fos = openfileoutput ("books.xml", context.mode_private);
        Fos.write (Xml.getbytes ("UTF-8"));
        catch (Exception e) {log.e (TAG, E.getmessage ());
  }
      }
    });

 }
}

The interface is two buttons, and by the way, put it on:

Clicking the "ReadXML" button will call the SAX parser to parse the document and print the relevant information on the log table:

Then clicking the "WriteXml" button will generate a books.xml file in the files directory under the application package:

Using the DOM parser:

The Dombookparser.java code is as follows:

Package com.scott.xml.parser;
Import Java.io.InputStream;
Import Java.io.StringWriter;
Import java.util.ArrayList;
Import java.util.List;
Import Javax.xml.parsers.DocumentBuilder;
Import Javax.xml.parsers.DocumentBuilderFactory;
Import Javax.xml.transform.OutputKeys;
Import Javax.xml.transform.Result;
Import Javax.xml.transform.Source;
Import Javax.xml.transform.Transformer;
Import Javax.xml.transform.TransformerFactory;
Import Javax.xml.transform.dom.DOMSource;
Import Javax.xml.transform.stream.StreamResult;
Import org.w3c.dom.Document;
Import org.w3c.dom.Element;
Import Org.w3c.dom.Node;
Import org.w3c.dom.NodeList;
Import Com.scott.xml.model.Book; public class Dombookparser implements Bookparser {@Override public list<book> parse (InputStream is) throws
    ption {list<book> books = new Arraylist<book> (); Documentbuilderfactory factory = Documentbuilderfactory.newinstance (); Get Documentbuilderfactory instance Documentbuilder Builder = Factory.newdocumenTbuilder ();  Get Documentbuilder instance Document doc = Builder.parse (is) from factory;
    Parsing the input stream gets the document instance Element rootelement = Doc.getdocumentelement ();
    NodeList items = rootelement.getelementsbytagname ("book");
      for (int i = 0; i < items.getlength (); i++) {Book book = new book ();
      Node item = Items.item (i);
      NodeList properties = Item.getchildnodes ();
        for (int j = 0; J < Properties.getlength (); j + +) {Node property = Properties.item (j);
        String nodename = Property.getnodename ();
        if (Nodename.equals ("id")) {Book.setid (Integer.parseint (Property.getfirstchild (). Getnodevalue ()));
        else if (nodename.equals ("name")) {Book.setname (Property.getfirstchild (). Getnodevalue ()); 
        else if (nodename.equals ("price")) {Book.setprice (Float.parsefloat () Property.getfirstchild (). Getnodevalue ());
    } books.add (book);
  return to books; @Override Public String serialIze (List<book> Books) throws Exception {Documentbuilderfactory factory = Documentbuilderfactory.newinstance ();
    Documentbuilder builder = Factory.newdocumentbuilder ();  Document doc = Builder.newdocument ();
    Create a new document by builder Element rootelement = doc.createelement ("books");
      for (book book:books) {Element bookelement = doc.createelement (' book ');
      Bookelement.setattribute ("id", Book.getid () + "");
      Element nameelement = doc.createelement ("name");
      Nameelement.settextcontent (Book.getname ());
      Bookelement.appendchild (nameelement);
      Element priceelement = doc.createelement ("price");
      Priceelement.settextcontent (Book.getprice () + "");
      Bookelement.appendchild (priceelement);
    Rootelement.appendchild (bookelement);
    } doc.appendchild (rootelement); Transformerfactory transfactory = Transformerfactory.newinstance ();//Get transformerfactory instance Transformer Transformer  = Transfactory.newtransformer (); From TransfactoRy obtain transformer instance transformer.setoutputproperty (outputkeys.encoding, "UTF-8");        Set the encoding mode of the output Transformer.setoutputproperty (outputkeys.indent, "yes");  Whether to automatically add extra blank Transformer.setoutputproperty (outputkeys.omit_xml_declaration, "no");
    Whether to ignore the XML declaration StringWriter writer = new StringWriter (); SOURCE Source = new Domsource (DOC); Indicates that the source of the document is doc result = new Streamresult (writer);//indicates that the target outcome is writer Transformer.transform (source, results);
  Start converting return writer.tostring ();

 }
}

And then mainactivity, just change one place:

Readbtn.setonclicklistener (New View.onclicklistener () {
@Override public
void OnClick (View v) {
  try {
    InputStream is = Getassets (). Open ("books.xml");       parser = new Saxbookparser ();
    Parser = new Dombookparser ();
    Books = Parser.parse (is);
    for (book book:books) {
      log.i (tag, book.tostring ());
    }
  catch (Exception e) {
    LOG.E (tag, e.getmess Age ());
  }
);

The execution results are the same.

Using the Pull parser:

The Pullbookparser.java code is as follows:

Package com.scott.xml.parser;
Import Java.io.InputStream;
Import Java.io.StringWriter;
Import java.util.ArrayList;
Import java.util.List;
Import Org.xmlpull.v1.XmlPullParser;
Import Org.xmlpull.v1.XmlSerializer;
Import android.util.Xml;
Import Com.scott.xml.model.Book; public class Pullbookparser implements Bookparser {@Override public list<book> parse (InputStream is) throws
    eption {list<book> books = null;
Book book = null;
Xmlpullparserfactory factory = Xmlpullparserfactory.newinstance ();
    Xmlpullparser parser = Factory.newpullparser (); Xmlpullparser parser = Xml.newpullparser ();        Create a Xmlpullparser instance Parser.setinput (IS, "UTF-8") by ANDROID.UTIL.XML;
    Set the input stream and indicate the encoding mode int eventtype = Parser.geteventtype ();
        while (EventType!= xmlpullparser.end_document) {switch (eventtype) {case xmlpullparser.start_document:
        Books = new Arraylist<book> ();
      Break Case XmlPullParser.START_TAG:if(Parser.getname (). Equals ("book"))
        {book = new book ();
          else if (Parser.getname (). Equals ("id")) {EventType = Parser.next ();
        Book.setid (Integer.parseint (Parser.gettext ()));
          else if (Parser.getname (). Equals ("name")) {EventType = Parser.next ();
        Book.setname (Parser.gettext ());
          else if (Parser.getname (). Equals ("price")) {EventType = Parser.next ();
        Book.setprice (Float.parsefloat (Parser.gettext ()));
      } break;
          Case XmlPullParser.END_TAG:if (Parser.getname (). Equals (' book ')) {books.add (book);
        book = null;
      } break;
    } EventType = Parser.next ();
  return to books; @Override public String Serialize (List<book> books) throws Exception {//Xmlpullparserfactory factory = Xml
Pullparserfactory.newinstance ();
    XmlSerializer serializer = Factory.newserializer (); XmlSerializer serializer = Xml.newseriAlizer ();
    A XmlSerializer instance is created by android.util.Xml stringwriter writer = new StringWriter ();  Serializer.setoutput (writer);
    Sets the output direction to writer Serializer.startdocument ("UTF-8", true);
    Serializer.starttag ("", "books");
      for [book Book:books] {Serializer.starttag ("", "book");
      Serializer.attribute ("", "id", Book.getid () + "");
      Serializer.starttag ("", "name");
      Serializer.text (Book.getname ());
      Serializer.endtag ("", "name");
      Serializer.starttag ("", "price");
      Serializer.text (Book.getprice () + "");
      Serializer.endtag ("", "price");
    Serializer.endtag ("", "book");
    } serializer.endtag ("", "books");
    Serializer.enddocument ();
  return writer.tostring ();

 }
}

Then make the following changes to Mainactivity:

Readbtn.setonclicklistener (New View.onclicklistener () {
  @Override public
  void OnClick (View v) {
    try {
      InputStream is = Getassets (). Open ("books.xml");         parser = new Saxbookparser ();         parser = new Dombookparser ();
      Parser = new Pullbookparser ();
      Books = Parser.parse (is);
      for (book book:books) {
        log.i (tag, book.tostring ());
      }
    catch (Exception e) {
      LOG.E (tag, e.getmess Age ());}}
);

Is the same as the other two execution results.

For these three kinds of parsers have advantages, I personally prefer to pull parser, because the SAX parser is too cumbersome to operate, Dom is not suitable for large documents, memory is small, only pull lightweight flexible, fast, occupy small memory, use very conveniently. Readers can also choose the appropriate analytical techniques according to their preferences.

I hope this article will help you with the Android program.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.