2

我正在寻找使用 Java 应用程序解析各种 XML 文档的最佳方法。我目前正在使用 SAX 和自定义内容处理程序执行此操作,并且效果很好 - 快速且稳定。

我决定探索具有相同程序的选项,该程序当前接收单一格式的 XML 文档,接收两种额外的 XML 文档格式,以及各种 XML 元素更改。我希望根据文档中的第一个“startElement”将 ContentHandler 换成适当的内容处理程序......但是,呃,呃,设置了 ContentHandler,然后解析了文档!

... constructor ...
{
SAXParserFactory spf = SAXParserFactory.newInstance();

try {
SAXParser sp = spf.newSAXParser();
parser = sp.getXMLReader();
parser.setErrorHandler(new MyErrorHandler());
} catch (Exception e) {} 

... parse StringBuffer ...
try {
parser.setContentHandler(pP);
parser.parse(new InputSource(new StringReader(xml.toString())));
return true;
} catch (IOException e) {
    e.printStackTrace();
} catch (SAXException e) {
    e.printStackTrace();
}
...

所以,我似乎无法以我最初认为的方式做到这一点。

话虽这么说,我认为这完全错误吗?用相同的 XML 处理代码解析多个离散的 XML 文档的最佳方法是什么? 我之前试图在更笼统的帖子中提问……但是,我认为我太含糊了。出于速度和效率的目的,我从未真正关注过 DOM,因为这些 XML 文档相当大,系统每隔几分钟就会收到大约 1200 个。这只是一种信息发送方式

使这个问题太长并增加我的困惑;以下是一些我想要一个 SAX、StAX 或 ?? 的各种 XML 文档的模型。解析器干净地处理。

产品.xml:

<products>
<product>
  <id>1</id>
  <name>Foo</name>
<product>
  <id>2</id>
  <name>bar</name>
</product>
</products>

商店.xml:

<stores>
<store>
  <id>1</id>
  <name>S1A</name>
  <location>CA</location>
</store>
<store>
  <id>2</id>
  <name>A1S</name>
  <location>NY</location>
</store>
</stores>

管理器.xml:

<managers>
<manager>
  <id>1</id>
  <name>Fen</name>
  <store>1</store>
</manager>
<manager>
  <id>2</id>
  <name>Diz</name>
  <store>2</store>
</manager>
</managers>
4

9 回答 9

3

据我了解,问题在于您在解析之前不知道文档的格式。您可以使用委托模式。我假设您没有针对 DTD/XSD/etcetera 进行验证,并且 DefaultHandler 拥有状态是可以的。

public class DelegatingHandler extends DefaultHandler {

    private Map<String, DefaultHandler> saxHandlers;
    private DefaultHandler delegate = null;

    public DelegatingHandler(Map<String, DefaultHandler> delegates) {
        saxHandlers = delegates;
    }

    @Override
    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
       if(delegate == null) {
           delegate = saxHandlers.get(name);
       }
       delegate.startElement(uri, localName, name, attributes);
    }

    @Override
    public void endElement(String uri, String localName, String name)
            throws SAXException {
        delegate.endElement(uri, localName, name);
    }

//etcetera...
于 2008-08-27T17:38:38.753 回答
2

你已经很好地解释了你想要做什么,但没有解释为什么。有几个 XML 框架可以简化 Java 对象与 XML 之间的编组和解组。

最简单的是我通常用来解析配置文件的Commons Digester 。但是如果你想处理 Java 对象,那么你应该看看CastorJiBXJAXBXMLBeansXStream或类似的东西。Castor 或 JiBX 是我最喜欢的两个。

于 2008-08-27T17:22:33.770 回答
2

我曾经尝试过 SAXParser,但是一旦我找到了XStream,我就再也没有使用过它。使用 XStream,您可以创建 Java 对象并将它们转换为 XML。将它们发送过来并使用 XStream 重新创建对象。非常易于使用、快速并创建干净的 XML。

无论哪种方式,您都必须知道要从 XML 文件中接收哪些数据。您可以通过不同的方式发送它们以了解要使用的解析器。或者有一个数据对象可以保存所有内容,但只填充一个结构(产品/商店/经理)。也许是这样的:

public class DataStructure {

    List<ProductStructure> products;

    List<StoreStructure> stors;

    List<ManagerStructure> managers;

    ...

    public int getProductCount() {
        return products.lenght();
    }

    ...
}

并用 XStream 转换为 XML 发送过来然后重新创建对象。然后用它做你想做的事。

于 2008-08-27T17:30:23.360 回答
2

请参阅XMLReader.setContentHandler()的文档,它说:

应用程序可以在解析过程中注册一个新的或不同的处理程序,并且 SAX 解析器必须立即开始使用新的处理程序。

因此,您应该能够创建一个SelectorContentHandler在第一个事件之前使用事件的startElement事件,基于该事件更改ContentHandlerXML 阅读器,并将第一个开始元素事件传递给新的内容处理程序。您只需将 传递XMLReaderSelectorContentHandler构造函数中的。如果您需要将所有事件传递给特定于词汇表的内容处理程序,SelectorContentHandler则必须缓存事件然后传递它们,但在大多数情况下,这不是必需的。

附带说明一下,我最近在几乎所有项目中都使用XOM来处理 XML ja,到目前为止,性能还不是问题。

于 2008-08-27T18:58:49.450 回答
1

贾克斯_ XML 绑定的 Java 体系结构。基本上,您创建一个定义 XML 布局的 xsd(我相信您也可以使用 DTD)。然后将 XSD 传递给 JAXB 编译器,编译器创建 Java 类来将 XML 文档编组和解组为 Java 对象。这真的很简单。

顺便说一句,jaxb 有命令行选项来指定要放置结果类的包名称等。

于 2008-08-27T17:20:14.523 回答
0

如果您想要更多的动态处理,Stax 方法可能会比 Sax 更好。这仍然是相当低级的;如果你想要更简单的方法,XStream 和 JAXB 是我的最爱。但它们确实需要非常严格的对象才能映射到。

于 2009-01-08T04:00:51.920 回答
0

同意 StaxMan,有趣的是,他希望你使用 Stax。它是一个基于拉的解析器,而不是您当前使用的推。不过,这将需要对您的代码进行一些重大更改。

于 2009-01-08T14:32:31.537 回答
0

:-)

是的,我对 Stax 有一些偏见。但正如我所说,数据绑定通常比流式解决方案更方便。但是,如果它是您想要的流式传输,并且不需要流水线(多个过滤阶段),Stax 比 SAX 更简单。

还有一件事:与 XOM 一样好(wrt 替代品),如果您不处理“以文档为中心”的 xml(~= xhtml 页面、docbook、开放式办公室文档),通常使用树模型不是正确的选择。对于数据交换、配置文件等数据绑定更方便、更高效、更自然。对于这些用例,只需对像 DOM 这样的树模型说不。所以,JAXB、XStream、JibX 都很好。或者,为了获得更多的口味,消化器、蓖麻、xmlbeans。

于 2009-01-27T20:26:30.253 回答
0

VTD-XML 以作为重型 XML 处理的最佳 XML 处理技术而闻名。请参阅下面的参考以获取证明

http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf

于 2016-04-09T19:24:20.560 回答