在XML标签之间跳转

时间:2009-09-18 09:00:51

标签: java xml sax

这是SAX的疑问。 我想在XML文件中处理子标记,只要它与父标记匹配。 例如:

<version>
    <parent tag-1>
       <tag 1>
       <tag 2>
     </parent tag-1 >
     <parent tag-2>
       <tag 1>
       <tag 2>
     </parent tag-2>
</version>

在上面的代码中,我想首先匹配父标记(即父标记-1或父标记``-2,基于用户输入),然后才处理它下面的子标记。 这可以在SAX解析器中完成,请记住SAX对DOM的控制有限,而且我是SAX和Java的新手吗?如果是这样,你能引用相应的方法吗? TIA

5 个答案:

答案 0 :(得分:1)

当然,可以通过记住父标签轻松完成。

通常,在解析xml标记时,人们使用堆栈来跟踪这些标记的族映射。您可以使用以下代码轻松解决您的案例:

Stack<Tag> tagStack = new Stack<Tag>();

public void startElement(String uri, String localName, String qName,
        Attributes attributes)
     if(localName.toLowerCase().equals("parent")){
          tagStack.push(new ParentTag());
     }else if(localName.toLowerCase().equals("tag")){
          if(tagStack.peek() instanceof ParentTag){
               //do your things here only when the parent tag is "parent"
          }
     }
}
public void endElement(String uri, String localName, String qName)
        throws SAXException{
     if(localName.toLowerCase().equals("parent")){
          tagStack.pop();
     }
}

或者您可以通过更新标记名来简单地记住您处于什么标记中:

String tagName = null;
public void startElement(String uri, String localName, String qName,
        Attributes attributes)
     if(localName.toLowerCase().equals("parent")){
          tagName = "parent";
     }else if(localName.toLowerCase().equals("tag")){
          if(tagName!= null && tagName.equals("parent")){
               //do your things here only when the parent tag is "parent"
          }
     }
}
public void endElement(String uri, String localName, String qName)
        throws SAXException{
     tagName = null;
}

但我更喜欢堆叠方式,因为它会跟踪你所有的祖先标签。

答案 1 :(得分:1)

如果你出于性能原因考虑这样做,那么无论如何,SAX都将打破整个文档。

但是,从代码良好的角度来看,你可以让SAX解析器通过用XMLFilter连接来返回不匹配的子节点。您可能仍然需要自己编写逻辑 - 类似Wing C. Chen's post中提供的逻辑 - 但不是将其放在应用程序逻辑上,而是将其抽象为过滤器实现。

这样可以让您更轻松地重复使用过滤逻辑,这可能会使您的应用程序代码更清晰,更容易理解。

答案 2 :(得分:1)

@Wing C.陈提出的解决方案不仅不错,但在你的情况下,我不会使用堆栈。

解析XML时堆栈的用例

堆栈和XML的常见用例是在使用自己的词法分析器(即具有容错性的手工XML解析器)时验证XML标记是否平衡。

它的一个具体示例是为Eclipse IDE构建XML文档的大纲。

何时使用SAX,拉解析器等

  • 解析大型XML文件时的内存效率

  • 您无需在文档中来回导航。

但是,使用SAX解析复杂文档可能会变得乏味,特别是如果您想根据某些条件将操作应用于节点。

何时使用像APis

这样的DOM
  • 您希望轻松访问节点

  • 您希望随时在文档中来回导航

  • 速度不是开发时间/可读性/维护的主要要求

我的推荐

如果您没有庞大的XML,请使用类似API的DOM并使用XPath选择节点。 我个人更喜欢Dom4J,但我不介意其他APis,如JDom,甚至Xpp3都支持XPath。

答案 3 :(得分:0)

每次点击标记时,SAX Parser都会在您的实现中调用一个方法。如果您需要不同的行为,具体取决于父项,则必须将其保存到变量中。

答案 4 :(得分:0)

如果要跳转到特定标记,则需要使用DOM解析器。这会将整个文档读入内存,然后提供访问树的特定节点的各种方法,例如按名称请求标记,然后询问该标记的子项。

因此,如果您不限于SAX,那么我会推荐DOM。我认为使用SAX over DOM的主要原因是DOM需要更多内存,因为整个文档一次加载。