Android - Общий XML Parser с использованием SAXParser - PullRequest
1 голос
/ 28 февраля 2011

Мне нужно написать класс синтаксического анализа 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>

Мне нужно разобрать идентификаторы блогов и идентификаторы постов из каналов, как указано выше.Из любого примера, который я нахожу на SAX, они не являются общими.Я хотел бы написать повторно используемую, есть ли у вас примеры, как я могу соответствующим образом изменить SAXParser?

Ответы [ 3 ]

3 голосов
/ 28 февраля 2011

SAX-парсеры являются управляемыми событиями парсерами.Вы пишете обработчик для каждого ТИПА узла XML (начальный элемент, конечный элемент, атрибут, текст и т. Д.), А затем анализатор выполняет итерации документа XML, и вам отправляются события SAX (= вызывается метод в вашем обработчике).

В вашем конкретном случае вы ищете две последовательности узлов:

  1. <feed><id>
  2. <feed><entry><id>

Итак, вы должныхранить некоторую информацию о состоянии внутри вашего обработчика, чтобы знать, где вы находитесь.Вот код (сам не пробовал, придется отлаживать):

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 голос
/ 28 февраля 2011

Попробуйте что-нибудь вроде этого:

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, так что вы можете настроить и разложить их в начале и конце элементов или всего документа, если хотите.

Надеюсь, это поможет, и близко к тому, что выс нетерпением жду.

1 голос
/ 28 февраля 2011

Проверьте мой ответ на Как проанализировать XML с помощью SAX-парсера .Это должно помочь вам.

...