2013-03-26 85 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