java sax parser mangles属性为xml 1.1

时间:2013-03-26 10:19:30

标签: java xml sax xml-1.1

我正在使用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个“lat”属性,这些属性都是“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个trkpts,并且都有两个属性叫做“lat”和“lon”。奇怪的是,lon值总是好的。

我通过直接复制/粘贴第一个trkpt在文本编辑器中创建了这个xml文件,所以我确定所有值都是相同的,我确定xml文件中没有带有有趣属性值的点,我确信没有非ascii字符值或实体代码或其他任何奇怪的文件。

我在使用Sun的JRE6,OpenJDK6和OpenJDK7的三台不同的机器上尝试了两种不同的操作系统。所以要么我做错了,要么这个特定的xml文件以某种方式与xml1.1不兼容,或者有一个普遍的sax bug(这似乎不太可能,因为我预计它会影响很多人)。再次请注意,使用xml1.0一切正常。还要注意,数字420并没有什么特别之处,只是如果文件只有100个条目,那么它们都可以正确解析。如果你有几千个条目,那么它们中的一定数量会以这种方式破坏它们的第一个属性值。属性值的长度似乎总是正确的,但是它会从文件中的错误点拉出字符。索引可能会溢出吗?

我尝试删除所有速度标记,但如果你有足够的trkpts,问题仍然存在。它对额外的空格也很敏感,因此如果我在trkpts之间添加换行符,则会出现不同点的问题或者返回不同的属性值。

1 个答案:

答案 0 :(得分:3)

这个错误已经存在于JDK XML解析器中多年,Sun和Oracle都没有对修复它有任何兴趣。我强烈建议优先使用Apache Xerces XML解析器。