我正在创建一个使用SAXparser获取某些XML的应用程序。 我正在解析xml,如果xml没有特定节点,我必须使用不同的URL重新启动SAXparser。
这意味着当我在startElement里面的XML处理程序中时,我必须打破/停止它并再次执行它。我怎样才能打破/停止/退出?
以下是一些可以解释的假代码:
private String browsLevel(String url) {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
URL sourceUrl = new URL(url);
MyXMLHandler myXMLHandler = new MyXMLHandler();
xr.setContentHandler(myXMLHandler);
xr.parse(new InputSource(sourceUrl.openStream()));
}
//external class in a separate document
public class MyXMLHandler extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// Im checking here if a special node exsists and if not I need to break/stop this and go to the Restart point above.
//I need to do something like this:
if (!localName.equals("mysspecialnode")) {
MyXMLHandler.break(); //????
browsLevel("a different url");
}
答案 0 :(得分:1)
抛出异常。 SAXException就足够了。如果文档很短,抛出异常的成本可能会高于仅允许SAX解析器完成的成本。
或者使用像kxml2这样的拉解析器,你可以控制文档流而不是SAX引擎 - 比使用DOM更重要。
答案 1 :(得分:0)
我还没有在SAX解析器中看到任何break方法,因为这是事件驱动的,所以绕过它需要一个布尔值作为成员变量,并在条件匹配时将其设为true并写入“return”语句并使用该布尔变量引用并返回来自所有其他事件方法(例如endElement和其他人,如果你想)。然后启动另一个URL的调用。 (写回复语句会更快地绕过所有事件,你可以发起你的电话)。
private String browsLevel(String url){ SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader();
URL sourceUrl = new URL(url);
MyXMLHandler myXMLHandler = new MyXMLHandler();
xr.setContentHandler(myXMLHandler);
xr.parse(new InputSource(sourceUrl.openStream()));
if(myXMLHandler.isStart == true)
{
// Now initiate a call here with different URL
browsLevel("a different url");
}
}
public class MyXMLHandler extends DefaultHandler
{
boolean isStart = false;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
// Now check for boolean flag
if(isStart)
{
return;
}
if (!localName.equals("mysspecialnode"))
{
isStart = true;
}
答案 2 :(得分:0)
首先,即使在某种程度上可以告诉SAX解析器在回调方法中以某种方式提前终止解析,从处理程序中再次调用browsLevel()也是一个坏主意。当然,处理程序由SAX解析器调用。处理程序必须执行其操作,然后将执行返回到SAX解析器。
另外,我认为你可能会误解处理程序中startElement()的目的。为每个元素开始标记按照它们在解析的XML文档中出现的顺序调用此方法。第一次调用startElement()将是文档中第一个元素开始标记。因此,如果第一个标记字符串或任何后续标记字符串不是“myspecialnode”,则if (!localName.equals("mysspecialnode"))
语句中的代码块将执行。换句话说,单独使用if
语句不足以检测特定的开始标记字符串是否出现在XML文档中的任何位置。
我的建议是您执行以下任一操作:
1:继续使用SAX解析器,但更多地研究SAX解析器文档,以便了解处理程序的用途及其中的方法。将为文档中存在的每个start元素调用处理程序及其startElement()方法。如果您感兴趣的数据仅包含在元素<myspecialnode ... >
中,那么您可以这样做:
public class MyXMLHandler extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (localName.equals("mysspecialnode")) {
// If you are here, then the XML document DOES contain <myspecialnode>. Now that you are here, you can parse the attributes
// that are contained in this node. You could also set a flag to indicate that you’re now inside the <myspecialnode> element,
// to indicate that subsequent start tags are nodes inside <myspecialnode>, until the point where you get a </myspecialnode>
// end tag.
// When parsing has finished, you check this flag and if it is false, you call
// the SAX parser again to parse "a different url".
}
基本上,使用SAX解析器,您的应用程序代码 通过处理程序按照XML文档中显示的顺序使用所有文档数据。
2:第二个选项是使用DOM解析器。 Android平台包含SAX和DOM解析器。 SAX的优点是它不必事先在内存中构建XML文档的文档对象模型;相反,它遍历文档并在解析文档时使用数据调用处理程序。这样做的缺点是,您必须能够按照数据在文档中显示的顺序处理数据,因为它会传递给处理程序。使用DOM解析器,您可以在初始构建XML文档模型时获得CPU和内存损失。但是,一旦完成,您就可以使用标准DOM调用来随机浏览XML文档,通过给定名称获取元素的节点列表等。我认为您可以实现您想要使用SAX的目标已经理解了处理程序如何更好地工作,但也可能值得做一个Android DOM解析器教程。