2011-05-17 49 views
8

我正在尋找一個解析器,它可以讓我成功解析破碎的xml,並採取「最佳猜測」的方法 - 例如。PHP是否存在寬鬆的寬容XML解析器?

<thingy> 
     <description> 
      something <b>with</b> bogus<br> 
      markup not wrapped in CDATA 
     </description> 
    </thingy> 

理想情況下,它會產生一個thingy對象,它具有一個description屬性和任何內部的標籤湯。

有關如何解決問題的其他建議(除開始使用有效標記外)。

非PHP解決方案(美麗的湯(蟒蛇)例如)不是外面的蒼白,但我寧願堅持當時的技能設置在公司

謝謝!

+3

它不是XML,如果它不嚴格;-) – 2011-05-17 13:37:10

+5

您沒有得到XML的觀點:XML的主要想法是,如果它遇到了一個問題,它會殺了你,你的家人,你的朋友和任何你曾經交談過的人。語法錯誤。沒有嚴厲錯誤處理的XML只是不再是XML ^^ – NikiC 2011-05-17 13:41:33

+3

@nikic - 我一直處於與不必處理由第三方提供的破碎的「XML」輸入的OP相同的位置, XML。雖然我同意這並不理想,但當數據必須導入並且我們無法讓第三方修復系統時,我們只需要處理它。 :-( – Spudley 2011-05-17 13:45:20

回答

4

您可以使用DOMDocument::loadHTML()(或DOMDocument::loadhtmlfile())將已損壞的XML轉換爲正確的XML。如果您不喜歡與DOMDocument對象打交道,請使用saveXML()並使用SimpleXML加載生成的XML字符串。

$dom = DOMDocument::loadHTMLfile($filepath); 
if (!$dom) 
{ 
    throw new Exception("Could not load the lax XML file"); 
} 
// Now you can work with your XML file using the $dom object. 


// If you'd like using SimpleXML, do the following steps. 
$xml = new SimpleXML($dom->saveXML()); 
unset($dom); 

我試過這個腳本:

<?php 
$dom = new DOMDocument(); 
$dom->loadHTMLFile('badformatted.xml'); 
if (!$dom) 
{ 
    die('error'); 
} 
$nodes = $dom->getElementsByTagName('description'); 
for ($i = 0; $i < $nodes->length; $i++) 
{ 
    echo "Node content: ".$nodes->item($i)->textContent."\n"; 
} 

從CLI執行此當輸出:

[email protected]:~/xml$ php test.php 

Warning: DOMDocument::loadHTMLFile(): Tag thingy invalid in badformatted.xml, line: 1 in /home/carlos/xml/test.php on line 3 

Warning: DOMDocument::loadHTMLFile(): Tag description invalid in badformatted.xml, line: 2 in /home/carlos/xml/test.php on line 3 
Node content: 
       something with bogus 
       markup not wrapped in CDATA 

[email protected]:~/xml$ 

編輯:一些小的修正和錯誤處理。

edit2:更改爲非靜態調用以避免E_STRICT錯誤,增加了測試用例。

+0

唉,都失敗了 - 由於borked XML而導致XML失敗,HTML因爲'invalid'(用於HTML)元素標籤而失敗。 – Wagemage 2011-05-17 14:07:40

+0

在我現在所做的測試中,它會發出關於未知html節點的警告,但它會正確加載所有元素(包括這些「未知」標記)。 – 2011-05-17 14:21:42

+0

使用XML示例查看我的更新示例 – 2011-05-17 14:30:37

1

一種替代方法是使用Tidy HTML庫(PHP binding here)首先清理HTML。這在相當多的相當可怕的輸入中生存下來,而且我曾經看到過人們在之前使用它來拼湊相當麻煩的HTML。

+0

這將是我的建議。預處理過程一旦完成,您只需不驗證它。我假設這是某人對RSS網頁飼料的想法? – Mel 2011-05-17 14:38:07

+0

有人對產品目錄的想法,甚至 - 呃,卡洛斯的答案是這樣做的,儘管我可能會按照你的建議繼續HTML整理。只是爲了確保內部標記不會與其他任何東西相混淆。 – Wagemage 2011-05-17 14:52:45