我正在使用SAX解析一些大型XML文件,我想问以下问题:XML文件结构复杂。如下所示:
<library>
<books>
<book>
<title></title>
<img>
<name></name>
<url></url>
</img>
...
...
</book>
...
...
</books>
<categories>
<category id="abcd">
<locations>
<location>...</location>
</locations>
<url>...</url>
</category>
...
...
</categories>
<name>...</name>
<url>...</url>
</library>
事实是这些文件每个超过50MB,并且在不同的上下文中重复许多标签,例如url在/ books / book / img下,也在/ library下和/ library / categories / category等下。
我的SAX解析器使用DefaultHandler的子类,我在其中覆盖了startElement和endElement方法(以及其他方法)。但问题是由于这些XML文件的业务逻辑,这些方法在代码行方面是巨大的。我使用了很多
if ("url".equalsIgnoreCase(qName)) {
// peek at stack and if book is on top
// ...
// else if category is on top
// ...
} else if (....) {
}
我想知道是否有更合适/正确/优雅的方式来执行xml解析。
谢谢大家
答案 0 :(得分:1)
可以做的是为不同的上下文实现单独的 ContentHandler
。例如,为<books>
写一个,为<categories>
写一个,为顶级一个。
然后,只要调用books
startElement
方法,就会立即使用XMLReader.setContentHandler()
切换ContentHandler
。然后,<books>
特定ContentHandler
切换回顶级处理程序,以便为endElement
调用books
方法。
这样每个ContentHandler
都可以专注于XML的特定部分,而不需要了解所有其他部分。
唯一丑陋的部分是特定处理程序需要知道顶级处理程序以及何时切换回它,这可以通过提供一个处理它的简单“处理程序堆栈”来解决。
答案 1 :(得分:0)
不确定你是否在问1)除了用一串字符串检查标签之外你还能做些什么吗?或者2)如果有一个长if-then-else类型语句的替代品。
1的答案不是我找到的。其他人可能会解决这个问题。
2的答案取决于您的域名。我看到的一种方法是,如果要点是从XML文件中水合一堆对象,那么你可以使用工厂方法。
因此,第一个工厂方法具有long if then else语句,只需将XML传递给适当的类。然后每个类都有一个类似constructYourselfFromXmlString的方法。这将改进您的设计,因为只有对象本身才能知道XML中的私有数据以保护它们。
这很难的原因是,如果你考虑一下,将对象导出到XML并导入回来确实违反了封装。没有什么可以做的,只是。这至少使事情变得更加封装。
HTH
答案 2 :(得分:0)
同意将对象导出为XML的观点是对封装的违反,使用SAX时,用于处理嵌套在不同长度的标签的实际技术并不是非常困难。
基本上,保留一个StringBuffer,它将在文档中维护您的“位置”,这将是一个目录,就像您当前所在的嵌套标记的表示一样。例如,如果字符串缓冲区的内容是/library/book/img/url
,那么您知道它是书中图像的URL,而不是某个类别的URL。
确保“路径跟踪”算法正确后,您可以使用字符串匹配更好地处理对象创建例程。而不是
if ("url".equalsIgnoreCase(qName)) {
...
}
你现在可以替换
if (location.equalsIgnoreCase("/library/book/img/url")) {
...
}
如果出于某种原因这对您没有吸引力,还有其他解决方案。例如,您可以创建一个SAX处理程序来实现一堆处理程序,其中顶部处理程序负责处理它的XML文档的一部分,并且一旦完成它就会从堆栈中弹出。使用这样的方案,每个对象都由它自己独特的单独处理程序创建,并且一些处理程序基本上检查并指导哪些“对象创建”处理程序在适当的时间被推入处理堆栈。
我使用过两种技术。两者都有优势,哪一个最好取决于输入和所需的对象。
答案 3 :(得分:0)
您可以重构SAX内容处理,以便注册一组规则,每个规则都有一个适用的测试,以查看它是否与元素匹配,以及执行时执行的操作。这正在接近XSLT处理模型,同时仍在进行流处理。或者你可以转向XSLT - 处理50Mb输入文件完全在现代XSLT处理器的能力范围内。
答案 4 :(得分:0)