0

这是 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

4

5 回答 5

1

无论如何,如果您出于性能原因考虑这样做,SAX 将通过整个文档进行假脱机。

但是,从代码美观的角度来看,您可以让 SAX 解析器不返回不匹配的子项,方法是使用XMLFilter将其连接起来。您可能仍然需要自己编写逻辑 - 类似于Wing C. Chen 的帖子中提供的内容 - 但与其将其放在应用程序逻辑中,您可以将其抽象为过滤器实现。

这将使您更轻松地重用过滤逻辑,并且可能使您的应用程序代码更清晰且更易于遵循。

于 2009-09-18T10:49:34.657 回答
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;
}

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

于 2009-09-18T09:10:54.230 回答
1

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

解析 XML 时堆栈的用例

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

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

何时使用 SAX、Pull 解析器等

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

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

然而,使用 SAX 解析复杂的文档可能会变得乏味,尤其是如果您想根据某些条件对节点应用操作。

何时使用 API 之类的 DOM

  • 您希望轻松访问节点

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

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

我的推荐

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

于 2009-09-18T12:18:47.987 回答
0

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

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

于 2009-09-18T10:54:12.363 回答
0

SAX 解析器将在您的实现中调用一个方法,每次它遇到一个标记。如果您想要根据父级的不同行为,则必须将其保存到变量中。

于 2009-09-18T09:10:57.733 回答