我正在寻找使用 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 个文档。这只是一种信息发送方式

让这个问题变得太长并增加我的困惑;下面是一些不同的 XML 文档的模型,我希望它们有一个 SAX、StAX 或 ??解析器干净地处理。

产品.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>
有帮助吗?

解决方案

据我了解,问题在于您在解析之前不知道文档是什么格式。您可以使用委托模式。我假设您没有针对 DTD/XSD/等进行验证,并且 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...

其他提示

你很好地解释了你想做什么,但没有解释为什么。有多种 XML 框架可以简化 Java 对象与 XML 的编组和解组。

最简单的是 公共消化器 我通常用它来解析配置文件。但是如果你想处理 Java 对象那么你应该看看 蓖麻, 吉宝新, 联合航空航天局, XMLBeans, 流媒体, ,或类似的东西。Castor 或 JiBX 是我最喜欢的两个。

我尝试过 SAXParser 一次,但是一旦我发现 流媒体 我再也没有回去过。使用 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 发送过来,然后重新创建对象。然后用它做你想做的事。

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

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

因此,您应该能够创建一个 SelectorContentHandler 消耗事件直到第一个 startElement 事件,基于此改变 ContentHandler 在 XML 读取器上,并将第一个开始元素事件传递给新的内容处理程序。你只需要通过 XMLReaderSelectorContentHandler 在构造函数中。如果你需要 全部 要传递给词汇特定内容处理程序的事件, SelectorContentHandler 必须缓存事件然后传递它们,但在大多数情况下这是不需要的。

顺便说一句,我最近用过 XOM 到目前为止,在我处理 XML ja 的几乎所有项目中,性能都不是问题。

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

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

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

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

:-)

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top