如何使用 SAX 解析器解析 XML

发布于 2024-10-14 21:26:23 字数 203 浏览 8 评论 0原文

我正在关注这个教程

它工作得很好,但我希望它返回一个包含所有字符串的数组,而不是包含最后一个元素的单个字符串。

有什么想法如何做到这一点?

I'm following this tutorial.

It works great but I would like it to return an array with all the strings instead of a single string with the last element.

Any ideas how to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

装纯掩盖桑 2024-10-21 21:26:23

因此,您想要构建一个 XML 解析器来解析像这样的 RSS 提要。

<rss version="0.92">
<channel>
    <title>MyTitle</title>
    <link>http://myurl.com</link>
    <description>MyDescription</description>
    <lastBuildDate>SomeDate</lastBuildDate>
    <docs>http://someurl.com</docs>
    <language>SomeLanguage</language>

    <item>
        <title>TitleOne</title>
        <description><![CDATA[Some text.]]></description>
        <link>http://linktoarticle.com</link>
    </item>

    <item>
        <title>TitleTwo</title>
        <description><![CDATA[Some other text.]]></description>
        <link>http://linktoanotherarticle.com</link>
    </item>

</channel>
</rss>

现在您有两个可以使用的 SAX 实现。您可以使用 org.xml.saxandroid.sax 实现。在发布一个短手示例后,我将解释两者的优缺点。

android.sax 实现

让我们从 android.sax 实现开始。

您首先必须使用 RootElementElement 对象定义 XML 结构。

无论如何,我会使用 POJO(普通旧 Java 对象)来保存您的数据。这就是所需的 POJO。

Channel.java

public class Channel implements Serializable {

    private Items items;
    private String title;
    private String link;
    private String description;
    private String lastBuildDate;
    private String docs;
    private String language;

    public Channel() {
        setItems(null);
        setTitle(null);
        // set every field to null in the constructor
    }

    public void setItems(Items items) {
        this.items = items;
    }

    public Items getItems() {
        return items;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }
    // rest of the class looks similar so just setters and getters
}

该类实现了 Serialized 接口,因此您可以将其放入 Bundle 中并使用它执行某些操作。

现在我们需要一个类来保存我们的项目。在本例中,我将扩展 ArrayList 类。

Items.java

public class Items extends ArrayList<Item> {

    public Items() {
        super();
    }

}

这就是我们的项目容器。我们现在需要一个类来保存每个项目的数据。

Item.java

public class Item implements Serializable {

    private String title;
    private String description;
    private String link;

    public Item() {
        setTitle(null);
        setDescription(null);
        setLink(null);
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    // same as above.

}

示例:

public class Example extends DefaultHandler {

    private Channel channel;
    private Items items;
    private Item item;

    public Example() {
        items = new Items();
    }

    public Channel parse(InputStream is) {
        RootElement root = new RootElement("rss");
        Element chanElement = root.getChild("channel");
        Element chanTitle = chanElement.getChild("title");
        Element chanLink = chanElement.getChild("link");
        Element chanDescription = chanElement.getChild("description");
        Element chanLastBuildDate = chanElement.getChild("lastBuildDate");
        Element chanDocs = chanElement.getChild("docs");
        Element chanLanguage = chanElement.getChild("language");

        Element chanItem = chanElement.getChild("item");
        Element itemTitle = chanItem.getChild("title");
        Element itemDescription = chanItem.getChild("description");
        Element itemLink = chanItem.getChild("link");

        chanElement.setStartElementListener(new StartElementListener() {
            public void start(Attributes attributes) {
                channel = new Channel();
            }
        });

        // Listen for the end of a text element and set the text as our
        // channel's title.
        chanTitle.setEndTextElementListener(new EndTextElementListener() {
            public void end(String body) {
                channel.setTitle(body);
            }
        });

        // Same thing happens for the other elements of channel ex.

        // On every <item> tag occurrence we create a new Item object.
        chanItem.setStartElementListener(new StartElementListener() {
            public void start(Attributes attributes) {
                item = new Item();
            }
        });

        // On every </item> tag occurrence we add the current Item object
        // to the Items container.
        chanItem.setEndElementListener(new EndElementListener() {
            public void end() {
                items.add(item);
            }
        });

        itemTitle.setEndTextElementListener(new EndTextElementListener() {
            public void end(String body) {
                item.setTitle(body);
            }
        });

        // and so on

        // here we actually parse the InputStream and return the resulting
        // Channel object.
        try {
            Xml.parse(is, Xml.Encoding.UTF_8, root.getContentHandler());
            return channel;
        } catch (SAXException e) {
            // handle the exception
        } catch (IOException e) {
            // handle the exception
        }

        return null;
    }

}

正如您所见,这是一个非常简单的示例。使用 android.sax SAX 实现的主要优点是您可以定义必须解析的 XML 的结构,然后只需将事件侦听器添加到适当的元素即可。缺点是代码变得相当重复且臃肿。

org.xml.sax 实现

org.xml.sax SAX 处理程序实现有点不同。

在这里,您不指定或声明 XML 结构,而只是监听事件。最广泛使用的事件是以下事件:

  • 文档开始
  • 文档结束
  • 元素开始
  • 元素结束
  • 元素开始和元素结束之间的字符

使用上面的 Channel 对象的示例处理程序实现如下所示。

示例

public class ExampleHandler extends DefaultHandler {

    private Channel channel;
    private Items items;
    private Item item;
    private boolean inItem = false;

    private StringBuilder content;

    public ExampleHandler() {
        items = new Items();
        content = new StringBuilder();
    }

    public void startElement(String uri, String localName, String qName, 
            Attributes atts) throws SAXException {
        content = new StringBuilder();
        if(localName.equalsIgnoreCase("channel")) {
            channel = new Channel();
        } else if(localName.equalsIgnoreCase("item")) {
            inItem = true;
            item = new Item();
        }
    }

    public void endElement(String uri, String localName, String qName) 
            throws SAXException {
        if(localName.equalsIgnoreCase("title")) {
            if(inItem) {
                item.setTitle(content.toString());
            } else {
                channel.setTitle(content.toString());
            }
        } else if(localName.equalsIgnoreCase("link")) {
            if(inItem) {
                item.setLink(content.toString());
            } else {
                channel.setLink(content.toString());
            }
        } else if(localName.equalsIgnoreCase("description")) {
            if(inItem) {
                item.setDescription(content.toString());
            } else {
                channel.setDescription(content.toString());
            }
        } else if(localName.equalsIgnoreCase("lastBuildDate")) {
            channel.setLastBuildDate(content.toString());
        } else if(localName.equalsIgnoreCase("docs")) {
            channel.setDocs(content.toString());
        } else if(localName.equalsIgnoreCase("language")) {
            channel.setLanguage(content.toString());
        } else if(localName.equalsIgnoreCase("item")) {
            inItem = false;
            items.add(item);
        } else if(localName.equalsIgnoreCase("channel")) {
            channel.setItems(items);
        }
    }

    public void characters(char[] ch, int start, int length) 
            throws SAXException {
        content.append(ch, start, length);
    }

    public void endDocument() throws SAXException {
        // you can do something here for example send
        // the Channel object somewhere or whatever.
    }

}

现在说实话,我无法真正告诉您此处理程序实现相对于 android.sax 的任何真正优势。不过,我可以告诉您现在应该非常明显的缺点。看一下 startElement 方法中的 else if 语句。由于我们有标签 </code>、<code>link</code> 和 <code>description</code>,我们必须在我们所在的 XML 结构中跟踪它们那一刻。也就是说,如果我们遇到 <code><item></code> 起始标记,我们会将 <code>inItem</code> 标志设置为 <code>true</code> 以确保将正确的数据映射到正确的对象,并且在 <code>endElement</code> 方法中,如果遇到 <code></item></code> 标记,我们会将该标志设置为 <code>false</code>。表示我们已经完成了该项目标签。

在这个例子中,管理起来非常容易,但是必须解析具有不同级别的重复标签的更复杂的结构就变得很棘手。在那里,您必须使用枚举来设置当前状态,并使用大量 switch/case 语句来检查您所在的位置,或者更优雅的解决方案是某种使用标签堆栈的标签跟踪器。

So you want to build a XML parser to parse a RSS feed like this one.

<rss version="0.92">
<channel>
    <title>MyTitle</title>
    <link>http://myurl.com</link>
    <description>MyDescription</description>
    <lastBuildDate>SomeDate</lastBuildDate>
    <docs>http://someurl.com</docs>
    <language>SomeLanguage</language>

    <item>
        <title>TitleOne</title>
        <description><![CDATA[Some text.]]></description>
        <link>http://linktoarticle.com</link>
    </item>

    <item>
        <title>TitleTwo</title>
        <description><![CDATA[Some other text.]]></description>
        <link>http://linktoanotherarticle.com</link>
    </item>

</channel>
</rss>

Now you have two SAX implementations you can work with. Either you use the org.xml.sax or the android.sax implementation. I'm going to explain the pro's and con's of both after posting a short hander example.

android.sax Implementation

Let's start with the android.sax implementation.

You have first have to define the XML structure using the RootElement and Element objects.

In any case I would work with POJOs (Plain Old Java Objects) which would hold your data. Here would be the POJOs needed.

Channel.java

public class Channel implements Serializable {

    private Items items;
    private String title;
    private String link;
    private String description;
    private String lastBuildDate;
    private String docs;
    private String language;

    public Channel() {
        setItems(null);
        setTitle(null);
        // set every field to null in the constructor
    }

    public void setItems(Items items) {
        this.items = items;
    }

    public Items getItems() {
        return items;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }
    // rest of the class looks similar so just setters and getters
}

This class implements the Serializable interface so you can put it into a Bundle and do something with it.

Now we need a class to hold our items. In this case I'm just going to extend the ArrayList class.

Items.java

public class Items extends ArrayList<Item> {

    public Items() {
        super();
    }

}

Thats it for our items container. We now need a class to hold the data of every single item.

Item.java

public class Item implements Serializable {

    private String title;
    private String description;
    private String link;

    public Item() {
        setTitle(null);
        setDescription(null);
        setLink(null);
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    // same as above.

}

Example:

public class Example extends DefaultHandler {

    private Channel channel;
    private Items items;
    private Item item;

    public Example() {
        items = new Items();
    }

    public Channel parse(InputStream is) {
        RootElement root = new RootElement("rss");
        Element chanElement = root.getChild("channel");
        Element chanTitle = chanElement.getChild("title");
        Element chanLink = chanElement.getChild("link");
        Element chanDescription = chanElement.getChild("description");
        Element chanLastBuildDate = chanElement.getChild("lastBuildDate");
        Element chanDocs = chanElement.getChild("docs");
        Element chanLanguage = chanElement.getChild("language");

        Element chanItem = chanElement.getChild("item");
        Element itemTitle = chanItem.getChild("title");
        Element itemDescription = chanItem.getChild("description");
        Element itemLink = chanItem.getChild("link");

        chanElement.setStartElementListener(new StartElementListener() {
            public void start(Attributes attributes) {
                channel = new Channel();
            }
        });

        // Listen for the end of a text element and set the text as our
        // channel's title.
        chanTitle.setEndTextElementListener(new EndTextElementListener() {
            public void end(String body) {
                channel.setTitle(body);
            }
        });

        // Same thing happens for the other elements of channel ex.

        // On every <item> tag occurrence we create a new Item object.
        chanItem.setStartElementListener(new StartElementListener() {
            public void start(Attributes attributes) {
                item = new Item();
            }
        });

        // On every </item> tag occurrence we add the current Item object
        // to the Items container.
        chanItem.setEndElementListener(new EndElementListener() {
            public void end() {
                items.add(item);
            }
        });

        itemTitle.setEndTextElementListener(new EndTextElementListener() {
            public void end(String body) {
                item.setTitle(body);
            }
        });

        // and so on

        // here we actually parse the InputStream and return the resulting
        // Channel object.
        try {
            Xml.parse(is, Xml.Encoding.UTF_8, root.getContentHandler());
            return channel;
        } catch (SAXException e) {
            // handle the exception
        } catch (IOException e) {
            // handle the exception
        }

        return null;
    }

}

Now that was a very quick example as you can see. The major advantage of using the android.sax SAX implementation is that you can define the structure of the XML you have to parse and then just add an event listener to the appropriate elements. The disadvantage is that the code get quite repeating and bloated.

org.xml.sax Implementation

The org.xml.sax SAX handler implementation is a bit different.

Here you don't specify or declare you XML structure but just listening for events. The most widely used ones are following events:

  • Document Start
  • Document End
  • Element Start
  • Element End
  • Characters between Element Start and Element End

An example handler implementation using the Channel object above looks like this.

Example

public class ExampleHandler extends DefaultHandler {

    private Channel channel;
    private Items items;
    private Item item;
    private boolean inItem = false;

    private StringBuilder content;

    public ExampleHandler() {
        items = new Items();
        content = new StringBuilder();
    }

    public void startElement(String uri, String localName, String qName, 
            Attributes atts) throws SAXException {
        content = new StringBuilder();
        if(localName.equalsIgnoreCase("channel")) {
            channel = new Channel();
        } else if(localName.equalsIgnoreCase("item")) {
            inItem = true;
            item = new Item();
        }
    }

    public void endElement(String uri, String localName, String qName) 
            throws SAXException {
        if(localName.equalsIgnoreCase("title")) {
            if(inItem) {
                item.setTitle(content.toString());
            } else {
                channel.setTitle(content.toString());
            }
        } else if(localName.equalsIgnoreCase("link")) {
            if(inItem) {
                item.setLink(content.toString());
            } else {
                channel.setLink(content.toString());
            }
        } else if(localName.equalsIgnoreCase("description")) {
            if(inItem) {
                item.setDescription(content.toString());
            } else {
                channel.setDescription(content.toString());
            }
        } else if(localName.equalsIgnoreCase("lastBuildDate")) {
            channel.setLastBuildDate(content.toString());
        } else if(localName.equalsIgnoreCase("docs")) {
            channel.setDocs(content.toString());
        } else if(localName.equalsIgnoreCase("language")) {
            channel.setLanguage(content.toString());
        } else if(localName.equalsIgnoreCase("item")) {
            inItem = false;
            items.add(item);
        } else if(localName.equalsIgnoreCase("channel")) {
            channel.setItems(items);
        }
    }

    public void characters(char[] ch, int start, int length) 
            throws SAXException {
        content.append(ch, start, length);
    }

    public void endDocument() throws SAXException {
        // you can do something here for example send
        // the Channel object somewhere or whatever.
    }

}

Now to be honest I can't really tell you any real advantage of this handler implementation over the android.sax one. I can however tell you the disadvantage which should be pretty obvious by now. Take a look at the else if statement in the startElement method. Due to the fact that we have the tags <title>, link and description we have to track there in the XML structure we are at the moment. That is if we encounter a <item> starting tag we set the inItem flag to true to ensure that we map the correct data to the correct object and in the endElement method we set that flag to false if we encounter a </item> tag. To signalize that we are done with that item tag.

In this example it is pretty easy to manage that but having to parse a more complex structure with repeating tags in different levels becomes tricky. There you'd have to either use Enums for example to set your current state and a lot of switch/case statemenets to check where you are or a more elegant solution would be some kind of tag tracker using a tag stack.

还在原地等你 2024-10-21 21:26:23

在许多问题中,需要针对不同目的使用不同类型的 xml 文件。我不会试图抓住这个巨大的空间,并从我自己的经历中讲述我需要什么。

Java,也许是我最喜欢的编程语言。此外,这种爱因你可以解决任何问题而没有必要拿出自行车这一事实而得到加强。

因此,我创建了一组运行数据库的客户端服务器,允许客户端远程在数据库服务器中输入条目。无需检查输入数据等,但这不是重点。

作为工作原则,我毫不犹豫地选择了以xml文件的形式传输信息。以下类型:

<? xml version = "1.0" encoding = "UTF-8" standalone = "no"?> 
<doc> 
<id> 3 </ id> 
<fam> Ivanov </ fam> 
<name> Ivan </ name> 
<otc> I. </ otc> 
<dateb> 10-03-2005 </ dateb> 
<datep> 10-03-2005 </ datep> 
<datev> 10-03-2005 </ datev> 
<datebegin> 09-06-2009 </ datebegin> 
<dateend> 10-03-2005 </ dateend> 
<vdolid> 1 </ vdolid> 
<specid> 1 </ specid> 
<klavid> 1 </ klavid> 
<stav> 2.0 </ stav> 
<progid> 1 </ progid> 
</ doc> 

使其更容易进一步阅读,除了说它是有关医生机构的信息。姓氏、名字、唯一 ID 等。一般来说,数据系列。这个文件安全的到达了服务器端,然后开始解析该文件。

在解析的两个选项中(SAX vs DOM)我选择了SAX,因为事实上他的工作更加聪明,而且他是第一个落入我手中的:)

所以。如您所知,为了成功使用解析器,我们需要重写 DefaultHandler 所需的方法。首先,连接所需的包。

import org.xml.sax.helpers.DefaultHandler; 
import org.xml.sax. *; 

现在我们可以开始编写解析器了,

public class SAXPars extends DefaultHandler {
   ... 
} 

让我们从startDocument()方法开始。顾名思义,他对文档开头的事件做出反应。在这里您可以挂起各种操作,例如内存分配或重置值,但我们的示例非常简单,因此只需标记适当消息的工作开始即可:

Override 
public void startDocument () throws SAXException {
   System.out.println ("Start parse XML ..."); 
} 

下一步。解析器遍历文档并满足其结构元素。启动方法startElement()。而事实上,他的出现是这样的:startElement(String namespaceURI, String localName, String qName, Attributes atts)。这里namespaceURI - 命名空间,localName - 元素的本地名称,qName - 本地名称与命名空间的组合(用冒号分隔)和atts - 该元素的属性。在这种情况下,一切都很简单。使用 qName'om 并将其放入某个服务线 thisElement 就足够了。这样我们就可以标记出我们目前所处的元素。

@Override 
public void startElement (String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
   thisElement = qName; 
} 

接下来,我们来了解一下会议项目的含义。这里包括方法字符()。他的形式为:characters(char[]ch,int start,int length)。那么这里一切都清楚了。 ch - 在此元素中包含字符串本身的文件。起点和长度 - 指示线路起点和长度的服务数量。

@Override 
public void characters (char [] ch, int start, int length) throws SAXException {
   if (thisElement.equals ("id")) {
      doc.setId (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("fam")) {
      doc.setFam (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("name")) {
      doc.setName (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("otc")) {
      doc.setOtc (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("dateb")) {
      doc.setDateb (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datep")) {
      doc.setDatep (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datev")) {
      doc.setDatev (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datebegin")) {
      doc.setDatebegin (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("dateend")) {
      doc.setDateend (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("vdolid")) {
      doc.setVdolid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("specid")) {
      doc.setSpecid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("klavid")) {
      doc.setKlavid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("stav")) {
      doc.setStav (new Float (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("progid")) {
      doc.setProgid (new Integer (new String (ch, start, length))); 
   } 
} 

啊,是的。我差点忘了。由于其目标是折叠 naparsennye 数据,因此说明了医生的类型。该类已定义并具有所有必需的 setter-getter。

下一个明显的元素结束,然后是下一个。负责结束endElement()。它向我们发出信号,表明该项目已结束,此时您可以执行任何操作。将继续。净化元素。

@Override 
public void endElement (String namespaceURI, String localName, String qName) throws SAXException {
   thisElement = ""; 
} 

整个文档结束后,我们就到了文件的末尾。工作结束文档()。在其中,我们可以释放内存,进行一些diagnostichesuyu打印等。在我们的例子中,只需写下解析结束的内容即可。

@Override 
public void endDocument () {
   System.out.println ("Stop parse XML ..."); 
} 

所以我们有一个类来解析 xml 我们的格式。全文如下:

import org.xml.sax.helpers.DefaultHandler; 
import org.xml.sax. *; 
 
public class SAXPars extends DefaultHandler {
 
Doctors doc = new Doctors (); 
String thisElement = ""; 
 
public Doctors getResult () {
   return doc; 
} 
 
@Override 
public void startDocument () throws SAXException {
   System.out.println ("Start parse XML ..."); 
} 
 
@Override 
public void startElement (String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
   thisElement = qName; 
} 
 
@Override 
public void endElement (String namespaceURI, String localName, String qName) throws SAXException {
   thisElement = ""; 
} 
 
@Override 
public void characters (char [] ch, int start, int length) throws SAXException {
   if (thisElement.equals ("id")) {
      doc.setId (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("fam")) {
      doc.setFam (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("name")) {
      doc.setName (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("otc")) {
      doc.setOtc (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("dateb")) {
      doc.setDateb (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datep")) {
      doc.setDatep (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datev")) {
      doc.setDatev (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datebegin")) {
      doc.setDatebegin (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("dateend")) {
      doc.setDateend (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("vdolid")) {
      doc.setVdolid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("specid")) {
      doc.setSpecid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("klavid")) {
      doc.setKlavid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("stav")) {
      doc.setStav (new Float (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("progid")) {
      doc.setProgid (new Integer (new String (ch, start, length))); 
   } 
} 
 
@Override 
public void endDocument () {
   System.out.println ("Stop parse XML ..."); 
} 
} 

我希望该主题有助于轻松呈现 SAX 解析器的本质。

不要严格判断第一篇文章:)我希望它至少对某人有用。

UPD:要运行此解析器,您可以使用以下代码:

SAXParserFactory factory = SAXParserFactory.newInstance (); 
SAXParser parser = factory.newSAXParser (); 
SAXPars saxp = new SAXPars (); 
 
parser.parse (new File ("..."), saxp); 

In many problems it is necessary to use different kinds of xml files for different purposes. I will not attempt to grasp the immensity and tell from my own experience what I needed all this.

Java, perhaps, my favorite programming language. In addition, this love is strengthened by the fact that you can solve any problem and come up with a bike is not necessary.

So, it took me to create a bunch of client-server running a database that would allow the client to remotely make entries in the database server. Needless to be checking input data, etc. and the like, but it's not about that.

As a principle of work, I, without hesitation, chose the transmission of information in the form of xml file. Of the following types:

<? xml version = "1.0" encoding = "UTF-8" standalone = "no"?> 
<doc> 
<id> 3 </ id> 
<fam> Ivanov </ fam> 
<name> Ivan </ name> 
<otc> I. </ otc> 
<dateb> 10-03-2005 </ dateb> 
<datep> 10-03-2005 </ datep> 
<datev> 10-03-2005 </ datev> 
<datebegin> 09-06-2009 </ datebegin> 
<dateend> 10-03-2005 </ dateend> 
<vdolid> 1 </ vdolid> 
<specid> 1 </ specid> 
<klavid> 1 </ klavid> 
<stav> 2.0 </ stav> 
<progid> 1 </ progid> 
</ doc> 

Make it easier to read any further, except to say that it is the information about doctors institutions. Last name, first name, unique id, and so on. In general, the data series. This file safely got on the server side, and then start parsing the file.

Of the two options parsing (SAX vs DOM) I chose SAX view of the fact that he works more bright, and he was the first I fell into the hands :)

So. As you know, to work successfully with the parser, we need to override the needed methods DefaultHandler's. To begin, connect the required packages.

import org.xml.sax.helpers.DefaultHandler; 
import org.xml.sax. *; 

Now we can start writing our parser

public class SAXPars extends DefaultHandler {
   ... 
} 

Let's start with the method startDocument (). He, as the name implies, reacts to an event beginning of the document. Here you can hang a variety of actions such as memory allocation, or to reset the values​​, but our example is pretty simple, so just mark the beginning of work of an appropriate message:

Override 
public void startDocument () throws SAXException {
   System.out.println ("Start parse XML ..."); 
} 

Next. The parser goes through the document meets the element of its structure. Starts method startElement (). And in fact, his appearance this: startElement (String namespaceURI, String localName, String qName, Attributes atts). Here namespaceURI - the namespace, localName - the local name of the element, qName- a combination of local name with a namespace (separated by a colon) and atts - the attributes of this element. In this case, all simple. It suffices to use qName'om and throw it into some service line thisElement. Thus we mark in which the element at the moment we are.

@Override 
public void startElement (String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
   thisElement = qName; 
} 

Next, meeting item we get to its meaning. Here include methods characters (). He has the form: characters (char [] ch, int start, int length). Well here everything is clear. ch - a file containing the string itself self-importance within this element. start and length - the number of service indicating the starting point in the line and length.

@Override 
public void characters (char [] ch, int start, int length) throws SAXException {
   if (thisElement.equals ("id")) {
      doc.setId (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("fam")) {
      doc.setFam (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("name")) {
      doc.setName (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("otc")) {
      doc.setOtc (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("dateb")) {
      doc.setDateb (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datep")) {
      doc.setDatep (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datev")) {
      doc.setDatev (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datebegin")) {
      doc.setDatebegin (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("dateend")) {
      doc.setDateend (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("vdolid")) {
      doc.setVdolid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("specid")) {
      doc.setSpecid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("klavid")) {
      doc.setKlavid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("stav")) {
      doc.setStav (new Float (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("progid")) {
      doc.setProgid (new Integer (new String (ch, start, length))); 
   } 
} 

Ah, yes. I almost forgot. As the object of which will be to fold naparsennye data speaks to the type of Doctors. This class is defined and has all the necessary setters-getters.

Next obvious element ends and it is followed by the next. Responsible for ending the endElement (). It signals to us that the item has ended and you can do anything at this time. Will proceed. Cleanse Element.

@Override 
public void endElement (String namespaceURI, String localName, String qName) throws SAXException {
   thisElement = ""; 
} 

Coming so the entire document, we come to the end of the file. Work endDocument (). In it, we can free up memory, do some diagnostichesuyu printing, etc. In our case, just write about what parsing ends.

@Override 
public void endDocument () {
   System.out.println ("Stop parse XML ..."); 
} 

So we got a class to parse xml our format. Here is the full text:

import org.xml.sax.helpers.DefaultHandler; 
import org.xml.sax. *; 
 
public class SAXPars extends DefaultHandler {
 
Doctors doc = new Doctors (); 
String thisElement = ""; 
 
public Doctors getResult () {
   return doc; 
} 
 
@Override 
public void startDocument () throws SAXException {
   System.out.println ("Start parse XML ..."); 
} 
 
@Override 
public void startElement (String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
   thisElement = qName; 
} 
 
@Override 
public void endElement (String namespaceURI, String localName, String qName) throws SAXException {
   thisElement = ""; 
} 
 
@Override 
public void characters (char [] ch, int start, int length) throws SAXException {
   if (thisElement.equals ("id")) {
      doc.setId (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("fam")) {
      doc.setFam (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("name")) {
      doc.setName (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("otc")) {
      doc.setOtc (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("dateb")) {
      doc.setDateb (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datep")) {
      doc.setDatep (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datev")) {
      doc.setDatev (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("datebegin")) {
      doc.setDatebegin (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("dateend")) {
      doc.setDateend (new String (ch, start, length)); 
   } 
   if (thisElement.equals ("vdolid")) {
      doc.setVdolid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("specid")) {
      doc.setSpecid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("klavid")) {
      doc.setKlavid (new Integer (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("stav")) {
      doc.setStav (new Float (new String (ch, start, length))); 
   } 
   if (thisElement.equals ("progid")) {
      doc.setProgid (new Integer (new String (ch, start, length))); 
   } 
} 
 
@Override 
public void endDocument () {
   System.out.println ("Stop parse XML ..."); 
} 
} 

I hope the topic helped to easily present the essence of the SAX parser.

Do not judge strictly first article :) I hope it was at least someone useful.

UPD: To run this parser, you can use this code:

SAXParserFactory factory = SAXParserFactory.newInstance (); 
SAXParser parser = factory.newSAXParser (); 
SAXPars saxp = new SAXPars (); 
 
parser.parse (new File ("..."), saxp); 

public class MainActivity extends AppCompatActivity {
   ListView lvPcsPost;
    ArrayList<String> name;
    ArrayList<String> price;
    ArrayList<String> Description;
    LayoutInflater layoutInflater;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lvPcsPost = (ListView) findViewById(R.id.lvPcsPost);
        name = new ArrayList<>();
        price = new ArrayList<>();
        Description = new ArrayList<>();
        new PostAsync().execute();
    }

    class PostAsync extends AsyncTask<Void, Void, Void> {
        ProgressDialog pd;
        XMLHelper helper;


        @Override
        protected void onPreExecute() {
            pd = ProgressDialog.show(MainActivity.this, "", "Loading...", true, false);
        }

        @Override
        protected Void doInBackground(Void... arg0) {
            helper = new XMLHelper();
            helper.get();
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            PostBaseAdapter postBaseAdapter = new PostBaseAdapter();
            lvPcsPost.setAdapter(postBaseAdapter);
            pd.dismiss();
        }

    }

    public class XMLHelper extends DefaultHandler {

        private String URL_MAIN = "http://uat.winitsoftware.com/ThemeManager/Data/Products/Products.xml";
        String TAG = "XMLHelper";

        Boolean currTag = false;
        String currTagVal = "";

        public void get() {
            try {
                SAXParserFactory factory = SAXParserFactory.newInstance();
                SAXParser mSaxParser = factory.newSAXParser();
                XMLReader mXmlReader = mSaxParser.getXMLReader();
                mXmlReader.setContentHandler(this);
                InputStream mInputStream = new URL(URL_MAIN).openStream();
                mXmlReader.parse(new InputSource(mInputStream));
            } catch (Exception e) {
                Log.e(TAG, "Exception: " + e.getMessage());
            }
        }

        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            if (currTag) {
                currTagVal = currTagVal + new String(ch, start, length);
                currTag = false;
            }
        }

        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            currTag = false;

            if (localName.equalsIgnoreCase("Name"))
                name.add(currTagVal);

            else if (localName.equalsIgnoreCase("Description"))
             Description.add(currTagVal);

            else if (localName.equalsIgnoreCase("Price"))
              price.add(currTagVal);

        }
        @Override
        public void startElement(String uri, String localName, String qName,
                                 Attributes attributes) throws SAXException {
            Log.i(TAG, "TAG: " + localName);

            currTag = true;
            currTagVal = "";
            if (localName.equals("Products"));
        }
    }

    public class PostBaseAdapter extends BaseAdapter {

        public PostBaseAdapter() {

        }

        @Override
        public int getCount() {
            return name.size();
        }

        @Override
        public Object getItem(int position) {
            return name.get(position);
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            layoutInflater = LayoutInflater.from(getApplicationContext());

            convertView = layoutInflater.inflate(R.layout.list_item_post, parent, false);
            TextView  txtPrice = (TextView) convertView.findViewById(R.id.txtPrice);
            TextView  txtDescription = (TextView) convertView.findViewById(R.id.txtDescription);
            TextView   txtName = (TextView) convertView.findViewById(R.id.txtName);
            ImageView   image = (ImageView) convertView.findViewById(R.id.Image);
            ImageView  bigImage = (ImageView) convertView.findViewById(R.id.BigImage);

                txtPrice.setText("Price : "+price.get(position));
                 txtDescription.setText("Description : "+Description.get(position));
                txtName.setText("Name : "+name.get(position));

            return convertView;
        }
    }
}
public class MainActivity extends AppCompatActivity {
   ListView lvPcsPost;
    ArrayList<String> name;
    ArrayList<String> price;
    ArrayList<String> Description;
    LayoutInflater layoutInflater;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lvPcsPost = (ListView) findViewById(R.id.lvPcsPost);
        name = new ArrayList<>();
        price = new ArrayList<>();
        Description = new ArrayList<>();
        new PostAsync().execute();
    }

    class PostAsync extends AsyncTask<Void, Void, Void> {
        ProgressDialog pd;
        XMLHelper helper;


        @Override
        protected void onPreExecute() {
            pd = ProgressDialog.show(MainActivity.this, "", "Loading...", true, false);
        }

        @Override
        protected Void doInBackground(Void... arg0) {
            helper = new XMLHelper();
            helper.get();
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            PostBaseAdapter postBaseAdapter = new PostBaseAdapter();
            lvPcsPost.setAdapter(postBaseAdapter);
            pd.dismiss();
        }

    }

    public class XMLHelper extends DefaultHandler {

        private String URL_MAIN = "http://uat.winitsoftware.com/ThemeManager/Data/Products/Products.xml";
        String TAG = "XMLHelper";

        Boolean currTag = false;
        String currTagVal = "";

        public void get() {
            try {
                SAXParserFactory factory = SAXParserFactory.newInstance();
                SAXParser mSaxParser = factory.newSAXParser();
                XMLReader mXmlReader = mSaxParser.getXMLReader();
                mXmlReader.setContentHandler(this);
                InputStream mInputStream = new URL(URL_MAIN).openStream();
                mXmlReader.parse(new InputSource(mInputStream));
            } catch (Exception e) {
                Log.e(TAG, "Exception: " + e.getMessage());
            }
        }

        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            if (currTag) {
                currTagVal = currTagVal + new String(ch, start, length);
                currTag = false;
            }
        }

        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            currTag = false;

            if (localName.equalsIgnoreCase("Name"))
                name.add(currTagVal);

            else if (localName.equalsIgnoreCase("Description"))
             Description.add(currTagVal);

            else if (localName.equalsIgnoreCase("Price"))
              price.add(currTagVal);

        }
        @Override
        public void startElement(String uri, String localName, String qName,
                                 Attributes attributes) throws SAXException {
            Log.i(TAG, "TAG: " + localName);

            currTag = true;
            currTagVal = "";
            if (localName.equals("Products"));
        }
    }

    public class PostBaseAdapter extends BaseAdapter {

        public PostBaseAdapter() {

        }

        @Override
        public int getCount() {
            return name.size();
        }

        @Override
        public Object getItem(int position) {
            return name.get(position);
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            layoutInflater = LayoutInflater.from(getApplicationContext());

            convertView = layoutInflater.inflate(R.layout.list_item_post, parent, false);
            TextView  txtPrice = (TextView) convertView.findViewById(R.id.txtPrice);
            TextView  txtDescription = (TextView) convertView.findViewById(R.id.txtDescription);
            TextView   txtName = (TextView) convertView.findViewById(R.id.txtName);
            ImageView   image = (ImageView) convertView.findViewById(R.id.Image);
            ImageView  bigImage = (ImageView) convertView.findViewById(R.id.BigImage);

                txtPrice.setText("Price : "+price.get(position));
                 txtDescription.setText("Description : "+Description.get(position));
                txtName.setText("Name : "+name.get(position));

            return convertView;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文