Android - 使用SAXParser的通用XML解析器

时间:2011-02-28 15:01:55

标签: android xml feed gdata-api saxparser

我需要编写一个XML解析类,我可以在整个Android应用程序中重用它,从我读过的SAXParser是最适合移动应用程序的。我正在使用本指南:

http://www.jondev.net/articles/Android_XML_SAX_Parser_Example

我想要解析的文档类型是来自Blogger GData API的提要 - 例如:

<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/&quot;CUIGRnc4fyp7ImA9Wx9SEEg.&quot;'>
    <id>tag:blogger.com,1999:user-464300745974.blogs</id>
    <updated>2010-11-29T17:58:47.937Z</updated>
    <title>Tim's Blogs</title>
    <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.blogger.com/feeds/blogid/blogs'/>
    <link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/blogid/blogs'/>
    <link rel='alternate' type='text/html' href='http://www.blogger.com/profile/blogid'/>
    <author>
        <name>Tim</name>
        <uri>http://www.blogger.com/profile/blogid</uri>
        <email>noreply@blogger.com</email>
    </author>
    <generator version='7.00' uri='http://www.blogger.com'>Blogger</generator>
    <openSearch:totalResults>2</openSearch:totalResults>
    <openSearch:startIndex>1</openSearch:startIndex>
    <openSearch:itemsPerPage>25</openSearch:itemsPerPage>
    <entry gd:etag='W/&quot;DUIBQHg-cCp7ImA9Wx9TF0s.&quot;'>
        <id>tag:blogger.com,1999:user-464300745974.blog-blogid</id>
        <published>2010-06-22T10:59:38.603-07:00</published>
        <updated>2010-11-26T02:32:31.658-08:00</updated>
        <title>Application Testing Blog</title>
        <summary type='html'>This blog is for testing the Android application.</summary>
        <link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/blogid/blogs/blogid'/>
        <link rel='alternate' type='text/html' href='http://devrum.blogspot.com/'/>
        <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://devrum.blogspot.com/feeds/posts/default'/>
        <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='http://www.blogger.com/feeds/blogid/posts/default'/>
        <link rel='http://schemas.google.com/blogger/2008#template' type='application/atom+xml' href='http://www.blogger.com/feeds/blogid/template'/>
        <link rel='http://schemas.google.com/blogger/2008#settings' type='application/atom+xml' href='http://www.blogger.com/feeds/blogid/settings'/>
        <author>
            <name>Tim</name>
            <uri>http://www.blogger.com/profile/blogid</uri>
            <email>noreply@blogger.com</email>
        </author>
    </entry>
    <entry gd:etag='W/&quot;C08HRXo4eSp7ImA9Wx9TE0o.&quot;'>
        <id>tag:blogger.com,1999:user-464300745974.blog-515600026106499737</id>
        <published>2010-06-22T10:59:00.328-07:00</published>
        <updated>2010-11-21T12:37:14.431-08:00</updated>
        <title>Development Blog</title>
        <summary type='html'>etc</summary>
        <link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/blogid/blogs/515600026106499737'/>
        <link rel='alternate' type='text/html' href='http://rumdev.blogspot.com/'/>
        <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rumdev.blogspot.com/feeds/posts/default'/>
        <link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='http://www.blogger.com/feeds/515600026106499737/posts/default'/>
        <link rel='http://schemas.google.com/blogger/2008#template' type='application/atom+xml' href='http://www.blogger.com/feeds/515600026106499737/template'/>
        <link rel='http://schemas.google.com/blogger/2008#settings' type='application/atom+xml' href='http://www.blogger.com/feeds/515600026106499737/settings'/>
        <author>
            <name>Tim</name>
            <uri>http://www.blogger.com/etc</uri>
            <email>noreply@blogger.com</email>
        </author>
    </entry>
</feed>

我需要解析博客ID并从上面的Feed中发布ID。从我在SAX上找到的任何例子来看,它们都不是通用的。我想写一个可重用的,你有任何例子我可以相应地修改SAXParser吗?

3 个答案:

答案 0 :(得分:3)

SAX解析器是事件驱动的解析器。您为每个TYPE类型的XML节点(开始元素,结束元素,属性,文本等)编写处理程序,然后解析器迭代XML文档并将SAX事件发送给您(=处理程序中的methodes被调用)。

在您的特定情况下,您正在寻找两个节点序列:

  1. <feed><id>
  2. <feed><entry><id>
  3. 因此,您必须在处理程序中存储一些状态信息,以了解您的位置。这是代码(没有自己尝试,你必须调试它):

    public class DataHandler extends DefaultHandler {
    
        private Feed feed;
        private Entry currentEntry;
        private boolean isId = false;
    
        public Feed getFeed() {
            return feed;
        }
    
        @Override
        public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
            if (localName.equals("feed")) {
                feed = new Feed();
            } else if (localName.equals("entry")) {
                currentEntry = new Entry();
            } else if (localName.equals("id")) {
                isId = true;
            }
        }
    
        @Override
        public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
            if (localName.equals("feed")) {
                // </feed> - do nothing, it's the end
            } else if (localName.equals("entry")) {
                // </entry> - save current entry and reset variable
                feed.entries.add(currentEntry);
                currentEntry = null;
            } else if (localName.equals("id")) {
                 isId = false;
            }
        }
    
        @Override
        public void characters(char ch[], int start, int length) {
            if(!isId) return;
    
            String chars = new String(ch, start, length);
            chars = chars.trim();
    
            if (currentEntry != null) {
                currentEntry.id = chars;
            } else {
                feed.id = chars;
            }
        }
    
        private class Feed {
            public String id;
            public List<Entry> entries = new ArrayList<Entry>();
        }
    
        private class Entry {
            public String id;
        }
    }
    

答案 1 :(得分:1)

How to parse XML using the SAX parser上查看我的答案。这应该对你有帮助。

答案 2 :(得分:1)

尝试以下内容:

public class XmlParser extends DefaultHandler{
    private static final int        STATE_FEED      = 0;
    private static final int        STATE_ID        = 1;
    private static int          sDepth          = 0;
    private static int          sCurrentState   = 0;
    private String              mTheString;
public XmlParser(){}

@Override
public void startDocument() throws SAXException{}

@Override
public void endDocument() throws SAXException{}

@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException{
    mTheString = "";
    sDepth++;
    if (qName.equals("feed")){
        sCurrentState = STATE_FEED;
        return;
    }
    if (qName.equals("id")){
                    sCurrentState = STATE_ID;
            return;
    }
    sCurrentState = 0;
}

@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException{
    sDepth--;
        switch (sCurrentState){
            case STATE_FEED:
                                   //Do something with the feed
                sCurrentState = 0;
                mTheString = "";
                break;
            case STATE_ID:
                // Save the ID or do whatever
                sCurrentState = 0;
                mTheString = "";
                break;
            default:
                //Do nothing
                mTheString = "";
                return;
        }
        mTheString = "";
}

@Override
public void characters(char ch[], int start, int length){
      mTheString = mTheString + new String(ch, start, length);
}

}

您可以使用以下内容访问自定义SAXParser:

InputStream stream = //whatever your stream is (the document)
XmlParser handler = new XmlParser(); // your custom parser
XMLReader xmlreader = XMLReaderFactory.createXMLReader();
xmlreader.setContentHandler(handler); 
xmlreader.parse(new InputSource(stream));
   // Then you can create a method in the handler, like getResults to return the list of elements or something here.

因此,您将自定义解析器传递给Xml Reader,并从源中获取结果。在Xml解析期间,处理程序从“开始文档”开始,然后遍历xml中的元素(在开始时调用startElement,在开头调用endElement)。在这两者之间调用字符方法 - 拾取字符(然后您可以在endElement中执行任何操作)。调用endDocument时解析器已完成,因此您可以根据需要在元素的开头和结尾或整个文档中进行设置和拆除。

希望这会有所帮助,并且接近您的目标。