2009-02-19 159 views
0

我有一個XML解析器,它在不完整的XML數據上崩潰。因此,提供給它的XML數據可能是下列之一:XML解析問題

<one><two>twocontent</two</one> 

<a/><b/> (the parser treats it as two root elements) 

也處理元素屬性(雖然上面未顯示)。

現在,問題是,當我從套接字讀取數據時,我得到了碎片中的數據。例如:

<one>one 

content</two> 

</one> 

因此,發送XML解析器之前,我必須建立一個有效的XML,並將其發送。 什麼編程構造(如迭代,遞歸等)將是最適合這種情況。

我用C++編程。

請幫忙。

+0

解析器崩潰是什麼意思?按照規範,XML解析器應該在遇到格式不正確的XML時放棄回家。 – 2009-02-19 08:46:14

+0

你不應該寫一個XML解析器。這就像從頭開始構建自己的汽車引擎。 :-) – 2009-02-19 08:48:55

回答

0

有沒有多個作家?爲什麼您的解析器不驗證XML?

使用樹,其中每個節點代表一個元素,並帶有一個髒位。節點的第一次出現將其標記爲骯髒,即您期待結束標記,除非該節點的形式爲<a/>。另外,你遇到的第一個元素是根。

當你點擊一個髒節點時,不斷推送節點在堆棧中,直到你點擊結束標記,當你彈出內容時。

+0

感謝那個dirkgently,它的工作就像一個魅力 – ardsrk 2009-02-20 04:39:37

1

由於XML結構是一個層次結構(樹),遞歸將是解決這個問題的最好方法。 您可以調用每個子項的遞歸併修復缺少的XML標識符。 基本上,你會做同樣的事情的DOM對象解析器會做,只有你會解析文件,以解決它的結構。 但是有一件事情,在我看來,就好像在這種方法中你要重寫XML解析器一樣。這不是時間的腰? 也許最好找到一種方法讓XML到達正確的結構,而不是試圖修復它。

0

在你的例子中,一旦你發現它缺失,你將如何確定內容中的哪個位置將開放<two>標記?正如他們所說,這是不平凡的。

2

什麼是從套接字連接的另一端餵給你的XML?正如你所說的,僅僅因爲你從一個套接字接收到它,你沒有任何意義。

如果套接字使用TCP(或具有類似屬性的自定義協議),則不應缺少XML的某些部分。因此,您應該能夠緩衝所有內容,直到另一端發出「文檔結束」信號,然後將其提供給您挑剔的XML解析器。

如果您使用的是UDP或其他「有損」協議,則需要重新考慮,因爲顯然無法通過隨機丟棄碎片的通道正確傳輸大型XML文檔。

7

簡短回答:你做錯了。

你的問題混淆了兩個不同的問題:

未在所有格式良好的XML 數據
  1. 解析,即所謂的標記湯。

    示例:由不懂XML的編程人員生成的文件或編碼實踐不好的文件。

    • 這不是不公平的說:一個不是格式良好的XML文件根本就不是一個XML文檔。每個正確的XML解析器都會拒絕它。理想情況下,您將努力糾正這些數據的來源,並確保生成正確的XML。

    • 或者,使用標記湯分析器,即進行糾錯的分析器。

      有用的標籤湯分析器通常實際上是HTML分析器。已經在另一個答案中指出了tidy

      確保您瞭解解析器實際執行哪些更正步驟,因爲沒有可以修復XML的通用方法。例如,特別整潔的「修復」數據非常積極,比真實的瀏覽器和HTML 5規範更具攻擊性。

  2. XML從插座,其中數據到達塊逐塊在一個流解析。在這種情況下,XML文檔可能會被視爲「無限」,並且在查看根元素的最終結束標記之前很久就會處理該塊。

    例如:XMPP是一個像這樣工作的協議。

    • 解決方案是使用基於拉的解析器,例如libxml2中的XMLTextReader API。

    • 如果需要XML子元素爲解析器的基於樹的數據結構,則可以爲每個正在讀取的元素構建樹結構,而不是整個文檔。