代码之家  ›  专栏  ›  技术社区  ›  Paul Reiners

用SAX解析器确定是否在叶节点

  •  0
  • Paul Reiners  · 技术社区  · 7 年前

    使用 org.xml.sax.helpers.DefaultHandler ,你能确定你是否在 endElement(String, String, String) ?

    或者需要使用DOM解析器来确定这一点?

    0 回复  |  直到 7 年前
        1
  •  9
  •   GhostCat    7 年前

    让我们从一些基本定义开始:

    (来自 here ). 最重要的是:这意味着XML文件有一个非常规则、简单的结构。例如,定义 节点就是这样:一个没有任何子节点的节点。

    现在:那个 endElement() 结束 节点的标记。假设您的XML具有有效的内容,这也意味着解析器为您提供了相应的 startElement()

    换句话说:您可以使用确定是否“结束”叶节点所需的所有信息:

    • 告诉你哪些元素结束了

    举个例子:

    <outer>
      <inner/>
    </outer>
    

    这将导致这样一系列事件/回调:

    • 事件:开始元素外部
    • 事件:开始元素内部
    • 事件:结束元素内部
    • 事件:结束元素外部

    所以,“显然”,当你的解析器 事件的历史,决定 inner outer 是叶节点是直的!

    因此,答案是:不,您不需要DOM解析器。最后,DOM还是用同样的信息构建的!如果DOM解析器可以推断对象的“范围”,那么SAX解析器也可以。

    但请注意:您仍然需要小心地实现跟踪“started”、“open”和“ended”标记的数据结构,例如,要正确确定:

    <outer> <inner> <inner/> </inner> </outer>
    

    外面的 内部的 ),和一个叶节点(内部 内部的 ).

        2
  •  4
  •   Compass    7 年前

    从实现的角度来看,您可以只使用一个布尔标志来实现这一点,跟踪元素是否是潜在的叶节点。每当您输入一个元素时,该标志将始终为true,但只有第一个实际的叶节点结束元素将应用叶节点逻辑。

    每当应用startElement时,可以重复重置此标志。

    isLeafNode 标志已设置。

    如果我们将XML想象成一个堆栈,那么可以看到这背后的逻辑推理。 startElements

    private boolean isLeafNode = false;
    
    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        isLeafNode = true;
    }
    
    public void endElement(String uri, String localName, String qName) {
        if(isLeafNode) {
            //do leaf node logic
        }
    
        isLeafNode = false;
    }
    

    因此,对于下面的XML,叶节点如下所示。

    <foo>
        <bar>Leaf</bar>
        <baz>
            <bop>Leaf</bop>
            <beep>Leaf</beep>
            <blip>
                <moo>Leaf</moo>
            </blip>
        </baz>
    </foo>