Java 在XML标记之间跳转

Java 在XML标记之间跳转,java,xml,sax,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>

这在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对DOM的控制有限,而且我是SAX和Java的新手,这可以在SAX解析器中实现吗?如果是的话,你能引用相应的方法吗?
TIA

当然,记住父标记可以很容易地完成

通常,在解析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();
     }
}

但是我更喜欢堆栈方式,因为它可以跟踪所有祖先标记。

当然,记住父标记可以很容易地完成

通常,在解析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();
     }
}

但是我更喜欢堆栈方式,因为它跟踪所有祖先标记。

SAX解析器将在实现中调用方法,每次它碰到一个标记。如果您希望根据父对象的不同而有不同的行为,则必须将其保存到变量中。

SAX解析器将在实现中调用方法,每次它碰到标记时。如果您希望根据父对象的不同而有不同的行为,则必须将其保存到变量中。

SAX无论如何都要浏览整个文档,如果您考虑这样做是出于性能原因的话

但是,从代码简洁性的角度来看,通过将SAX解析器与。您可能仍然需要自己编写逻辑(类似于中提供的逻辑),但是您可以将其抽象为过滤器实现,而不是将其放在应用程序逻辑中


这将使您更容易地重用过滤逻辑,并且可能会使您的应用程序代码更干净、更易于理解。

SAX无论如何都会浏览整个文档,如果您考虑这样做是出于性能原因的话

但是,从代码简洁性的角度来看,通过将SAX解析器与。您可能仍然需要自己编写逻辑(类似于中提供的逻辑),但是您可以将其抽象为过滤器实现,而不是将其放在应用程序逻辑中


这将使您更容易地重用过滤逻辑,并且可能会使您的应用程序代码更干净、更易于理解。

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


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

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


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

由@Wing C.Chen提出的解决方案非常不错,但在您的情况下,我不会使用堆栈

解析XML时堆栈的用例

堆栈和XML的一个常见用例是,例如,在使用您自己的lexer(即带有容错功能的手工XML解析器)时,验证XML标记是否平衡

一个具体的例子是为EclipseIDE构建XML文档的大纲

何时使用SAX、拉式解析器等

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

  • 您不需要在文档中来回导航

但是,使用SAX解析复杂文档可能会变得单调乏味,特别是如果您希望根据某些条件对节点应用操作的话

何时使用类似DOM的API

  • 您希望轻松访问节点

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

  • 与开发时间/可读性/维护相比,速度不是主要要求

我的推荐

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

由@Wing C.Chen提出的解决方案非常不错,但在您的情况下,我不会使用堆栈

解析XML时堆栈的用例

堆栈和XML的一个常见用例是,例如,在使用您自己的lexer(即带有容错功能的手工XML解析器)时,验证XML标记是否平衡

一个具体的例子是为EclipseIDE构建XML文档的大纲

何时使用SAX、拉式解析器等

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

  • 您不需要在文档中来回导航

但是,使用SAX解析复杂文档可能会变得单调乏味,特别是如果您希望根据某些条件对节点应用操作的话

何时使用类似DOM的API