【发布时间】:2012-12-30 03:44:05
【问题描述】:
我遇到了需要读取多个 xml 文件并从中构建单个模型的情况。遗憾的是,这些文件是由我绝对无法更改的遗留系统生成的。
其中一个给我带来麻烦的 XML 文件看起来或多或少像这样(经过更改以删除专有数据):
<resource lang="en" dataId="900">
numbered content here, 900-919 ...
<string name="920-name">Document Shredder</string>
<string name="920-desc">A machine ideal for destroying documents that deserve it. It can cross-shred anything from tissue paper to small netbooks with minimal noise. Remember, hackers can't access the documents if you've shredded the drives.</string>
<string name="920-cat">office,appliance</string>
<string name="921-name">Plastic Ladle</string>
<string name="921-desc">This is a big plastic ladle, ideal for soups and sauces.</string>
<string name="921-cat">kitchen,utensils</string>
... similar numbered content here, 922-934 ...
<string name="935-name">Green Laser Pointer</string>
<string name="935-desc">A High-Powered green laser pointer, ideal for irritating cats.</string>
<string name="935-cat">office,tool</string>
<string name="936-name">Black Metal Filing Cabinet</string>
<string name="936-desc">A large, metal cabinet (black) built to store hanging file folders.</string>
<string name="936-cat">office,storage</string>
... similar numbered content here, 937-994
</resource>
我将其解析为List<CString>,其中CString.java 是:
public class CString {
public String name;
public String desc;
@Override
public String toString() {
return "CString {!name: " + name + " !body: " + body + "}\n";
}
}
我尝试过使用DocumentBuilder,当它不起作用时,就使用普通的SaxParser。但是,无论我如何处理它,当我回顾我的CStrings 时,我有一些正文实际上包含文档不同部分的未解析标签。例如,打印出我前面提到的List<CString> 可能会产生类似的结果:
[ CStrings for 900-919 ...
, CString {!name: 920-name !body: Document Shredder}
, CString {!name: 920-desc !body: irritating cats.</string>
<string name="935-cat">office,tool</string>
<string name="936-name">Black Metal Filing Cabinet</e. Remember, hackers can't access the documents if you've shredded the drives.}
, CString {!name: 920-cat !body: office,appliance}
, CString {!name: 921-name !body: Plastic Ladle}
, CString {!name: 921-desc !body: This is a big plastic ladle, ideal for soups and sauces.}
, CString {!name: 921-cat !body: kitchen,utensils}
... CStrings for 922-934 ...
, CString {!name: 935-name !body: Green Laser Pointer}
, CString {!name: 935-desc !body: A High-Powered green laser pointer, ideal for irritating cats.}
, CString {!name: 935-cat !body: office,tool}
, CString {!name: 936-name !body: Black Metal Filing Cabinet}
, CString {!name: 936-desc !body: A large, metal cabinet (black) built to store hanging file folders.}
, CString {!name: 936-cat !body: office,storage}
... CStrings for 937-994
]
在我的代码的SaxParser 版本中,我的DefaultHandler 中有以下characters 方法:
public void characters(char ch[], int start, int length) throws SAXException {
String value = new String(ch, start, length).trim();
switch(currentQName.toString()) { // currentQName is a StringBuilder that holds just the current xml element's name
case "string":
if (value.contains("</string")) {
System.err.println("!!! Parse Error !!! " + value);
}
}
正如您可能已经猜到的那样,产生:
!!! Parse Error !!! irritating cats.</string>
<string name="935-cat">office,tool</string>
<string name="936-name">Black Metal Filing Cabinet</e. Remember, hackers can't access the documents if you've shredded the drives.
我通常不会问这种深奥的问题,尤其是当我无法提供具体的数据和代码时,但谷歌搜索似乎没有任何我能够确定的东西,当然还有代码不会抛出(或抑制)任何异常。
我注意到的一件事是,当数据有误时,如上面 920-desc 的 CString 所示,在这种情况下,错误数据的长度为 138 个字符,而且并非巧合的是,好的数据恰好包含 139 个字符变成它应该是的样子。这让我觉得这是某种缓冲问题。但是,无论我是让DocumentBuilder 管理缓冲区,还是尝试使用直接的SaxParser 更手动地管理它们,我仍然每次都在相同的地方得到完全相同的错误文本。最后,在处理较短的字符串、name 和 cat 时,我从未注意到任何错误的文本,我认为这也指向 char 缓冲区问题。
任何想法都会有所帮助!
【问题讨论】:
-
这很奇怪。我唯一能想到的是,如果 xml 缺少一些双引号 " 或一些标签右括号或包含一些未加引号的特殊字符,如角括号和
&之类的字符。您的处理程序对我来说看起来是正确的。或者,也许缓冲区在解析时被修改。还要检查您发布的解析错误,那里有一些奇怪的东西:`文件柜。记住,` -
问题出在源文件中。
DocumentBuilder每天被数十万人使用,因此出现这种明显错误的可能性微乎其微。我最好的建议是您在十六进制编辑器中查看源文件,看看实际内容是什么。 -
另外:您不是从服务器检索这些文件,是吗?如果是,请查看检索文件的代码。
-
@parsifal 文件从服务器下载到目录,然后从本地系统解析。读完文件后,我还检查了我把它们写回来的地方,据我所知,它们似乎是完整的。至于查看原件的十六进制内容,您会寻找什么样的东西?
-
十六进制编辑器将向您显示一般的“不属于的字符”,例如来自错误编码或超出 XML 允许范围的字符。虽然,老实说,那些应该导致解析器抛出异常。它还可以让您查看文本,而不会被您认为正确的标记所误导。
标签: java xml-parsing saxparser