我正在使用 java 的 sax 类来解析 xml 文件。如果 xml 文件显示 1.0 版,一切正常,但如果显示 1.1 版,则某些属性会被破坏,给我错误的结果,但不会引发任何异常。
我的 xml 文件基本上是这样的:
<?xml version="1.1" encoding="UTF-8" ?>
<gpx>
<trk>
<name>Name of the track</name>
<trkseg>
<trkpt lat="12.3456789" lon="1.2345678">
<ele>1234</ele>
<time>2013-03-26T12:34:56Z</time>
<speed>0</speed>
</trkpt>
... and then 419 further identical copies of this trkpt
</trkseg>
</trk>
</gpx>
所以我期望,当我使用 sax 解析这个文件时,会找到 420 个 trkpt 标签,并且每个标签都有 lat 和 lon 属性。特别是,我希望找到 420 个“纬度”属性,它们都是“12.3456789”。
对于解析,我构造了一个处理程序对象并将其提供给该本地文件的流:
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
inStream = new FileInputStream(file);
saxParser.parse(inStream, handler);
System.out.println("done");
处理程序类扩展org.xml.sax.helpers.DefaultHandler
并且只有一种方法startElement
来响应 trkpt 标记的打开:
public void startElement(String uri, String localName, String qName, Attributes attributes)
{
if (qName.equals("trkpt") && attributes != null
&& attributes.getLength() == 2
&& attributes.getValue(0).charAt(0) != '1')
{
// The trkpt tag has two attributes
// but the value of the first one doesn't begin with '1'
System.out.println(attributes.getQName(0) + " = " + attributes.getValue(0));
}
super.startElement(uri, localName, qName, attributes);
}
那么结果如何呢?如果 xml 文件的版本为 1.0,那么我看到的只是“完成”。找到了 420 个 trkpt 标签,它们都有两个属性,第一个总是被称为“lat”,这个属性的值总是以“1”开头,正如我所料。伟大的!
如果将 xml 文件更改为version="1.1"
在第一行指定,则会得到以下输出:
lat = :34.56Z</t
lat = :56Z</time
done
所以即使我所有的 420 点都应该相同,但其中两个给了我一个完全错误的属性值。不抛出异常。仍然找到了 420 个 trkpt,它们都有两个属性,称为“lat”和“lon”。奇怪的是,lon 值总是可以的。
我通过直接复制/粘贴第一个 trkpt 在文本编辑器中创建了这个 xml 文件,所以我确定所有值都是相同的,我确定 xml 文件中没有具有有趣属性值的点,而且我确保文件没有非 ascii 字符值或实体代码或任何其他奇怪的东西。
我已经在具有两个不同操作系统的三台不同机器上使用 Sun 的 JRE6、OpenJDK6 和 OpenJDK7 进行了尝试。所以要么我做错了什么,要么这个特定的 xml 文件与 xml1.1 不兼容,或者存在一个广泛存在的 sax 错误(这似乎不太可能,因为我认为它会影响很多人)。再次请注意,使用 xml1.0 一切正常。另请注意,数字 420 没有什么特别之处,只是如果文件只有 100 个条目,那么它们都会被正确解析。如果您有数千个条目,那么其中一定数量的条目会以这种方式破坏它们的第一个属性值。属性值的长度似乎总是正确的,但它会从文件中的错误点提取字符。也许索引溢出?
我尝试删除所有速度标签,但如果您有足够的 trkpts,问题仍然存在。它对额外的空格也很敏感,因此如果我在 trkpts 之间添加换行符,问题会出现在不同的点上或返回不同的属性值。