跳过使用sax的节点

4

在解析过程中,是否可以跳过某些节点?如果可以,如何实现?skippedEntity与此有什么关系吗?

考虑以下XML:

<?xml version="1.0"?>

<nutrition>

<daily-values>
    <total-fat units="g">65</total-fat>
    <saturated-fat units="g">20</saturated-fat>
    <cholesterol units="mg">300</cholesterol>
    <sodium units="mg">2400</sodium>
    <carb units="g">300</carb>
    <fiber units="g">25</fiber>
    <protein units="g">50</protein>
</daily-values>

</nutrition>

我希望跳过“钠”元素。
3个回答

8
您可以尝试以下操作:

您可以像下面这样做:

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.XMLReader;

public class Demo {

    public static void main(String[] args) throws Exception {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();
        xr.setContentHandler(new MyContentHandler(xr));
        xr.parse("input.xml");
    }
}

MyContentHandler

这个类负责处理你的XML文档。当你遇到一个想要忽略的节点时,你可以使用IgnoringContentHandler来替换它,这将会吞噬该节点的所有事件。

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class MyContentHandler extends DefaultHandler {

    private XMLReader xmlReader;

    public MyContentHandler(XMLReader xmlReader) {
        this.xmlReader = xmlReader;
    }

    public void startElement(String uri, String localName, String qName,
            Attributes atts) throws SAXException {
        if ("sodium".equals(qName)) {
            xmlReader.setContentHandler(new IgnoringContentHandler(xmlReader,
                    this));
        } else {
            System.out.println("START " + qName);
        }
    }

    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        System.out.println("END " + qName);
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        System.out.println(new String(ch, start, length));
    }

}

IgnoringContentHandler

当忽略内容处理程序完成事件捕获后,它会将控制权传回到您的主ContentHandler。

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class IgnoringContentHandler extends DefaultHandler {

    private int depth = 1;
    private XMLReader xmlReader;
    private ContentHandler contentHandler;

    public IgnoringContentHandler(XMLReader xmlReader, ContentHandler contentHandler) {
        this.contentHandler = contentHandler;
        this.xmlReader = xmlReader;
    }

    public void startElement(String uri, String localName, String qName,
            Attributes atts) throws SAXException {
        depth++;
    }

    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        depth--;
        if(0 == depth) {
           xmlReader.setContentHandler(contentHandler);
        }
    }

}

@vtd-xml-author - 我已经将代码切换为扩展DefaultHandler而不是直接实现ContentHandler,这应该使代码更易于理解。在标准SAX解析中,链接内容处理程序是一种非常强大的机制。 - bdoughan
由于所有这些方法的默认行为都是“什么也不做”,所以我很难看出除了设置一个内容处理程序,然后再将其设置回来之外,这会实现什么。我的MyContentHandler已经不会做比您准备的更多的事情了。 - Alkanshel

3
请编辑您的帖子,包括一个示例XML和对“跳过节点”含义的描述。
由于解析器在每个事件上获得控制权,您可以根据任何条件选择不执行任何操作。如果您想跳过整个子树,您必须在遇到子树的开始元素时设置全局标志,并在结束元素时清除该标志;然后使用该标志来控制包含节点的处理。

我添加了xml,我想跳过"sodium"元素。 - London
好的,“skip”是什么意思?在SAX解析器中,你可以控制...... 你会收到解析事件,并且可以做任何想做的事情。你会得到每个标签的start-element事件,当标签名称为“sodium”时,你可以编写逻辑来返回,忽略数据。编辑您的帖子并展示您在Java中尝试的内容。 - Jim Garrison

1

很遗憾,我没有权限评论其他答案。我只是想纠正“Wayne”错误的断言,即Blaise的答案“不起作用”。我已经尝试过这段代码,它确实输出了除钠之外的所有示例数据值,我认为这正是OP所寻求的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接