2013-03-26 70 views
4

我使用java的萨克斯类来解析XML文件。如果xml文件提到版本1.0,一切正常,但如果它说版本1.1,然后某些的属性会发生损坏,给我错误的结果,但不会抛出任何形式的异常。java萨克斯解析器mangles属性为XML 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标签,并为他们每个人都有纬度和经度属性。特别是,我期望找到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错误(这似乎不太可能,因为我认为它会影响很多人)。请再次注意,使用xml1.0它一切正常。另外请注意,420号没有什么特别之处,只是如果文件只有100个条目,那么它们都会被正确解析。如果您有几千个条目,那么其中一定数量的条目会以这种方式获得其第一个属性值。属性值的长度似乎总是正确的,但它将字符从文件中的错误位置拉出来。索引溢出也许?

我试着删除所有的速度标签,但如果您有足够的trkpts,问题仍然存在。它对额外的空格也很敏感,所以如果我在trkpt之间添加换行符,问题会发生在不同的点上,或者返回不同的属性值。

+2

这可能是相关的:http://andrius.velykis。lt/2012/04/xml-11-long-attributes-in-java-6/ – 2013-03-26 10:35:46

+0

听起来像是xml解析器中的一个bug,对于我来说,您使用的是哪个Java版本或哪个xml解析器?此外,属性的顺序不是由xml定义的,最好用'attributes.getValue(“lat”)'替换'attributes.getValue(0)'。 – 2013-03-26 10:40:20

+0

正如我所说的,我正在使用JRE的内置sax解析,并且我尝试了Sun6,OpenJDK6和OpenJDK7。我不关心第一个属性是lat还是lon,它的值仍然应该以'1'开始。 – Penfold 2013-03-26 10:47:52

回答

3

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

+0

我尝试搜索它,但没有找到任何东西。它是否在官方bug跟踪器上报告?它是否标记为wontfix? – Penfold 2013-03-26 15:02:53

+0

对不起,我不知道。我想我至少在五年前报道过它,但我在跟踪器中发现它时遇到了麻烦。但是我可能从来没有报告过它,因为当你没有回应时,你放弃了报告错误。无论如何,它每隔几个月就会出现一个错误报告,指出有人针对撒克逊人提出的问题,并且当他们切换到使用Apache Xerces时,错误总是消失。 – 2013-03-26 18:19:27

+1

谢谢。我尝试使用Xerces,并且(迄今为止)无法以相同的方式使它失败。所以我认为对我来说最好的做法是尝试使用Xerces,如果不可用,请回退到内置的sax解析器(适用于xml 1.0)。 – Penfold 2013-03-27 14:15:16