问题描述
我下面这个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?
推荐答案
所以,你想建立一个XML解析器解析一个RSS提要像这样的。
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>
现在你有两个SAX实现的,你可以工作。要么你使用的org.xml.sax
或 android.sax
的实施。我要发布一个简短投手例如亲的和反对的双方后解释。
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实施
让我们先从 android.sax
的实施。
您先使用 rootElement的
和元素
对象来定义的XML结构。
You have first have to define the XML structure using the RootElement
and Element
objects.
在任何情况下,我将努力使用POJO(简单Java对象),这将保存数据。这里将是POJO的需要。
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
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.
现在我们需要一个类来保存我们的项目。在这种情况下,我只是要延长的ArrayList
类。
Now we need a class to hold our items. In this case I'm just going to extend the ArrayList
class.
Items.java
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
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的结构。其缺点是,code得到相当重复和臃肿。
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实施
在的org.xml.sax
SAX处理程序实现是一个有点不同。
The org.xml.sax
SAX handler implementation is a bit different.
在这里,您没有指定或声明你的XML结构,但只是听事件。最广泛使用的是以下事件:
Here you don't specify or declare you XML structure but just listening for events. The most widely used ones are following events:
- 文档启动
- 文件完
- 元素开始
- 元素结束
- 元素的开始和结束元素之间的字符
使用上述通道对象的示例处理程序实现看起来是这样的。
An example handler implementation using the Channel object above looks like this.
示例
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
一个你真正的优势。不过,我可以告诉你,这应该是pretty的明显现在的缺点。看看该否则,如果在的startElement
方法说明。由于这样的事实,我们有标记&LT;冠军&GT;
,链接
和的说明
,我们必须在XML结构,我们目前跟踪那里。也就是说,如果我们遇到一个&LT;项目&GT;
开始标记,我们将 inItem
标志真正的
,以确保我们正确的数据映射到正确的对象,并在的endElement
方法,我们设置了标志,以假
如果我们遇到一个&LT; /项目&GT;
标记。以突出显示我们正在与该项目的标签完成。
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.
在本例中为pretty的易于管理的,但有分析一个更复杂的结构与重复标签在不同的层次变得非常棘手。还有你必须要么使用枚举的例子来设置您的当前状态和大量的开关/箱的statemenets检查你在哪里或者一个更优雅的解决方案将是某种形式的标记跟踪器的使用标签栈。
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.
这篇关于如何使用SAX解析器解析XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!