【问题标题】:Skipping nodes with sax用萨克斯跳过节点
【发布时间】:2011-03-22 09:32:48
【问题描述】:

解析时是否可以跳过节点以及如何,这个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>

我想跳过“钠”元素

【问题讨论】:

    标签: java xml sax


    【解决方案1】:

    请编辑您的帖子以包含示例 XML 和对“跳过节点”的含义的描述。

    由于您的解析器可以控制每个事件,因此您可以根据您想要的任何标准选择不执行任何操作。如果要跳过整个子树,则必须在遇到子树的开始元素时设置一个全局标志,并在结束元素处清除标志;然后使用该标志来控制包含节点的处理。

    【讨论】:

    • 我添加了xml,我想跳过“钠”元素
    • 好的,“跳过”是什么意思?在 SAX 解析器中,您可以控制...您可以处理解析事件,并且可以做任何您想做的事情。您将获得每个标签的起始元素事件,当标签名称为“sodium”时,您可以编写逻辑只返回,而忽略数据。编辑您的帖子并展示您迄今为止在 Java 中所做的尝试。
    【解决方案2】:

    您可以执行以下操作:

    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 解析中非常强大的机制。
    • 由于所有这些方法的默认行为是“什么都不做”,除了设置一个内容处理程序反过来设置它之外,我很难看到它完成了什么。 MyContentHandler 已经不会做任何超出您准备的事情了
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      相关资源
      最近更新 更多