Parse XML using SAX
SAX is an xml parser with high resolution speed and low memory usage. It is suitable for Android and other mobile devices. An event-driven file is used to parse an XML file. That is to say, it does not need to parse a complete file. In the process of parsing a document in order of content, SAX checks whether the currently read characters are valid for a part of the XML syntax. If yes, the event is triggered. The so-called events are actually some callback methods, which are defined in the ContentHandler interface. Below are some common ContentHandler interface methods:
StartDocument ()
When a document starts, call this method to perform preprocessing.
EndDocument ()
In contrast to the above method, when the document ends, you can call this method to do some aftercare work.
StartElement (String namespaceURI, StringlocalName, String qName, Attributes atts)
This method is triggered when a start tag is read. NamespaceURI is the namespace, localName is the tag name without the namespace prefix, and qName is the tag name with the namespace prefix. You can use atts to obtain all the attribute names and corresponding values. It should be noted that an important feature of SAX is its stream processing. When a tag is encountered, it will not record the previously encountered tag, that is, in startElement () all the information you know in the method is the name and attribute of the tag. As for the nested structure of the tag, the name of the Upper-layer tag, whether there is sub-meta, and other information related to the structure, they are all unknown, and they all need your program to complete. This makes it easier to program and process SAX than DOM.
EndElement (String uri, String localName, String name)
This method corresponds to the above method and calls this method when an end tag is encountered.
Characters (char [] ch, int start, intlength)
This method is used to process the content read in the XML file. The first parameter is the file string content, and the next two parameters are the start position and length of the read string in this array, use new String (ch, start, length) to obtain the content.
As long as the ContentHandler interface class is provided for SAX, the class will be notified (in fact, SAX calls the callback method in this class ). Because ContentHandler is an interface, it may be inconvenient to use. Therefore, SAX also sets a Helper class for it: DefaultHandler, which implements the ContentHandler interface, however, all the methods are empty. During implementation, you only need to inherit the class and then override the corresponding method. The code for parsing itcast. xml using SAX is as follows:
Public static List <Person> readXML (InputStream inStream ){
Try {
SAXParserFactoryspf = SAXParserFactory. newInstance ();
SAXParsersaxParser = spf. newSAXParser (); // create a parser
// Set attributes related to the parser. http://xml.org/sax/features/namespaces= true indicates enabling the namespace feature
// SaxParser. setProperty ("http://xml.org/sax/features/namespaces", true );
XMLContentHandlerhandler = new XMLContentHandler ();
SaxParser. parse (inStream, handler );
InStream. close ();
Returnhandler. getPersons ();
} Catch (Exception e ){
E. printStackTrace ();
}
Return null;
}
You do not need to add any jar files. For the code implementation of XMLContentHandler, see the following remarks on this page.
DOM parsing XML
In addition to using SAX to parse XML files, you can also use the familiar DOM to parse XML files. When the DOM parses an XML file, all the content of the XML file is stored in the memory as an object tree. Then, you can use the dom api to traverse the XML tree and retrieve the required data. The code that uses DOM to operate XML looks intuitive and is simpler than the implementation based on SAX in some aspects. However, because the DOM needs to store all the content of the XML file in the memory as an object tree, the memory consumption is relatively large, especially for mobile devices running Android, because the resources of devices are precious, we recommend that you use SAX to parse XML files. Of course, it is feasible to use DOM if the content of XML files is small. Run the following code:
Import java. io. InputStream;
Import java. util. ArrayList;
Import java. util. List;
Import javax. xml. parsers. DocumentBuilder;
Importjavax. xml. parsers. DocumentBuilderFactory;
Import org. w3c. dom. Document;
Import org. w3c. dom. Element;
Import org. w3c. dom. Node;
Import org. w3c. dom. NodeList;
Importcn. itcast. xml. domain. Person;
/**
* Use Dom to parse xml files
*
*/
Public class DomXMLReader {
Public static List <Person> readXML (InputStream inStream ){
List <Person> persons = new ArrayList <Person> ();
DocumentBuilderFactoryfactory = DocumentBuilderFactory. newInstance ();
Try {
Documentbuilderbuilder = factory. newdocumentbuilder ();
Documentdom = builder. parse (instream );
Elementroot = Dom. getdocumentelement ();
Nodelistitems = root. getelementsbytagname ("person"); // search for all person nodes
For (INT I = 0; I <items. getlength (); I ++ ){
Personperson = new person ();
// Obtain the first person Node
ElementpersonNode = (Element) items. item (I );
// Obtain the id attribute value of the person Node
Person. setId (newInteger (personNode. getAttribute ("id ")));
// Obtain all subnodes under the person node (blank nodes and name/age elements between labels)
Nodelistchildsnodes = personnode. getchildnodes ();
For (Int J = 0; j <childsnodes. getlength (); j ++ ){
Nodenode = (node) childsnodes. Item (j );
// Determine whether it is an element type
If (node. getnodetype () = node. element_node) {element childnode = (element) node;
// Determine whether the name element is used
If ("name". Equals (childnode. getnodename ())){
// Obtain the text node under the name element, and then obtain the data person. setname (childnode. getfirstchild (). getnodevalue () from the text node ());
} Else if ("Age". Equals (childnode. getnodename ())){
Person. setage (newshort (childnode. getfirstchild (). getnodevalue ()));
}
}
}
Persons. add (person );
}
InStream. close ();
} Catch (Exception e ){
E. printStackTrace ();
}
Returnpersons;
}
PULL parsing XML
In addition to using SAX and DOM to parse XML files, you can also use the Android built-in Pull parser to parse XML files. The Running Method of the Pull parser is similar to that of the SAX Parser. It provides similar events, such as the start element and end element events. You can use parser. next () to enter the next element and trigger the corresponding event. The event is sent as a numeric code, so you can use a switch to process the event you are interested in. When parsing an element, call parser. nextText () to obtain the value of the next Text element.
Use the Pull parser to read itcast. xml Code
Import org. xmlpull. v1.XmlPullParser;
Import android. util. Xml;
Import cn. itcast. xml. domain. Person;
Public class PullXMLReader {
Public static List <Person> readXML (InputStream inStream ){
XmlPullParserparser = Xml. newPullParser ();
Try {
Parser. setinput (instream, "UTF-8 ");
Inteventtype = parser. geteventtype ();
Personcurrentperson = NULL;
List <person> Persons = NULL;
While (eventtype! = Xmlpullparser. end_document ){
Switch (eventtype ){
Casexmlpullparser. start_document: // document start event, which can be initialized and processed
Persons = new arraylist <person> ();
Break;
Casexmlpullparser. start_tag: // start element event
Stringname = parser. getname ();
If (name. inclusignorecase ("person ")){
Currentperson = new person ();
Currentperson. setid (newinteger (parser. getattributevalue (null, "ID ")));
} Else if (currentperson! = NULL ){
If (name. inclusignorecase ("name ")){
Currentperson. setname (parser. nexttext (); // if it is followed by a text element, its value is returned.
} Else if (name. Your signorecase ("age ")){
CurrentPerson. setAge (newShort (parser. nextText ()));
}
}
Break;
CaseXmlPullParser. END_TAG: // End Element event
If (parser. getName (). inclusignorecase ("person") & currentPerson! = Null ){
Persons. add (currentPerson );
CurrentPerson = null;
}
Break;
}
EventType = parser. next ();
}
InStream. close ();
Returnpersons;
} Catch (Exception e ){
E. printStackTrace ();
}
Returnnull;
}
}
Sometimes, we need to generate an XML file. There are many ways to generate an XML file. For example, we can use only one StringBuilder to group XML content and then write the content into the file; you can also use the pull parser to generate XML files by using DOM APIs. We recommend that you use the Pull parser.
Use the Pull parser to generate a myitcast. xml file with the same content as the itcast. xml file, and the code generates an XML file ):
File xmlFile = new File ("myitcast. xml ");
FileOutputStream outStream = newFileOutputStream (xmlFile );
OutputStreamWriter outStreamWriter = newOutputStreamWriter (outStream, "UTF-8 ");
BufferedWriter writer = newBufferedWriter (outStreamWriter );
WriteXML (persons, writer );
Writer. flush ();
Writer. close ();
If you only want to get the generated xml string content, you can use StringWriter:
StringWriter writer = new StringWriter ();
WriteXML (persons, writer );
String content = writer. toString ();
Public static StringwriteXML (List <Person> persons, Writer writer ){
XmlSerializer serializer = Xml. newSerializer ();
Try {
Serializer. setOutput (writer );
Serializer. startDocument ("UTF-8", true );
// The first parameter is the namespace. If the namespace is not used, you can set it to null.
Serializer. startTag ("", "persons ");
For (Person person: persons ){
Serializer. startTag ("", "person ");
Serializer. attribute ("", "id", person. getId (). toString ());
Serializer. startTag ("", "name ");
Serializer. text (person. getName ());
Serializer. endTag ("", "name ");
Serializer. startTag ("", "age ");
Serializer. text (person. getAge (). toString ());
Serializer. endTag ("", "age ");
Serializer. endTag ("", "person ");
}
Serializer. endTag ("", "persons ");
Serializer. endDocument ();
Return writer. toString ();
} Catch (Exception e ){
E. printStackTrace ();
}
Return null;
}