0

我制作了一个 SAX 解析器,用于解析带有许多不同标签的 XML 文件。出于性能原因,我选择了 SAX 而不是 DOM。我很高兴我做到了,因为它运行得又快又好。我目前唯一的问题是主类(它扩展了 DefaultHandler)有点大,而且看起来不太容易。它包含一个巨大的 if/elseif 块,我在其中检查标签名称,并带有一些嵌套的 if 用于读取特定属性。此块位于 StartElement 方法中。

有什么好干净的方法来拆分它吗?我想要一个读取文件的主类,然后是每个标签的处理程序。在这个标记处理程序中,我想读取该标记的属性,对它们进行处理,然后返回主处理程序读取下一个标记,该标记再次被重定向到适当的处理程序。

我的主处理程序还有一些全局 Collection 变量,它们收集有关我用它解析的所有文档的信息。理想情况下,我可以从标签处理程序向这些集合中添加一些东西。

如果可能的话,一个代码示例将非常有帮助。我在此站点上阅读了有关处理程序堆栈的内容,但没有代码示例,我无法重现它。

提前致谢 :)

4

1 回答 1

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.
    }
}
于 2013-03-18T16:10:03.763 回答