我已经制作了一个SAX解析器,用于解析具有许多不同标签的XML文件。出于性能原因,我选择了SAX而不是DOM。我很高兴我这样做,因为它工作得很快很好。我目前唯一的问题是主类(扩展DefaultHandler)有点大而且不容易看到。它包含一个巨大的if / elseif块,我在其中检查标记名称,其中一些嵌套if用于读取特定属性。该块位于StartElement方法中。
有什么好的干净方法可以解决这个问题吗?我想有一个读取文件的主类,然后是每个标签的Handler。在这个标记处理程序中,我想读取该标记的属性,对它们执行某些操作,然后返回主处理程序以读取下一个标记,该标记再次被重定向到适当的处理程序。
我的主处理程序还有一些全局Collection变量,它们收集有关我用它解析的所有文档的信息。理想情况下,我可以从Tag Handlers中为这些集合添加一些内容。
如果可能,代码示例将非常有用。我在这个网站上读到了一个关于Handler Stack的东西,但没有代码示例我无法重现它。
提前致谢:)
答案 0 :(得分:3)
我建议设置一系列SAX过滤器。 SAX过滤器就像任何其他SAX处理程序一样,除了它有另一个SAX处理程序在事件完成时将事件传递给它。它们经常用于对XML流执行一系列转换,但它们也可用于按您希望的方式对事物进行分解。
你没有提到你正在使用的语言,但你提到DefaultHandler所以我会假设Java。首先要做的是编写过滤器代码。在Java中,您可以通过实现XMLFilter(或者更简单地通过子类化XMLFilterImpl)来实现此目的。
import java.util.Collection;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.XMLFilterImpl;
public class TagOneFilter extends XMLFilterImpl {
private Collection<Object> collectionOfStuff;
public TagOneFilter(Collection<Object> collectionOfStuff) {
this.collectionOfStuff = collectionOfStuff;
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
if ("tagOne".equals(qName)) {
// Interrogate the parameters and update collectionOfStuff
}
// Pass the event to downstream filters.
if (getContentHandler() != null)
getContentHandler().startElement(uri, localName, qName, atts);
}
}
接下来,您的主类,它实例化所有过滤器并将它们链接在一起。
import java.util.ArrayList;
import java.util.Collection;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public class Driver {
public static void main(String[] args) throws Exception {
Collection<Object> collectionOfStuff = new ArrayList<Object>();
XMLReader parser = XMLReaderFactory.createXMLReader();
TagOneFilter tagOneFilter = new TagOneFilter(collectionOfStuff);
tagOneFilter.setParent(parser);
TagTwoFilter tagTwoFilter = new TagTwoFilter(collectionOfStuff);
tagTwoFilter.setParent(tagOneFilter);
// Call parse() on the tail of the filter chain. This will finish
// tying the filters together before executing the parse at the
// XMLReader at the beginning.
tagTwoFilter.parse(args[0]);
// Now do something interesting with your collectionOfStuff.
}
}