2013-03-25 79 views
2

因此,我使用simplexml與PHP中的XML解析,但我發現我需要解析的一些文件包含錯誤。當然,我可以手動編輯每一個有問題的文件,但是在大約10000多個文件中,這將永遠需要我。如何在PHP中使用Simplexml分析錯誤的XML文件?

好吧,關於錯誤。當您嘗試打開瀏覽器的XML文件,這個消息顯示了:

Specification mandate value for attribute error

警告:simplexml_load_string():實體:行2:解析錯誤:在屬性檢查規範任務值。 ..

我找到了ff。標籤被觸發錯誤(這裏:運輸代替檢驗):

<Public Transport Rules> 
<PublicTransport id="0"> 
<Issued>null</Issued> 
<Files>&lt;localfile&gt; 
      &lt;location&gt;Citybus&lt;/location&gt; 
      &lt;format&gt;Events&lt;/format&gt; 
    &lt;/localfile&gt; 
</Files> 
</PublicTransport> 
</Public Transport Rules> 

的空間在標籤內導致了問題,顯然。這些標籤在文件中不止一次出現。

我認爲simplexml解析它在瀏覽器中看到的(面值),所以如果你的XML文件有問題,它將無法正常解析。我想通過閱讀源文件來解析PHP,或者從那裏編輯文件。但似乎任何fopens打開您在瀏覽器頁面閱讀的內容。

現在一直被這個問題困住了。任何意見,將不勝感激。

謝謝!

+0

一個XML文件中應遵循XML規範有效,100%有效。然而,你可以檢查goutte或symfony/domcrawler庫來獲取html內容。 – mpm 2013-03-25 17:01:03

+0

所以我唯一的解決方案是改變每一個問題文件? – demenzia 2013-03-25 17:03:25

回答

1

DOM功能旨在對付無效的標記,所以你可以給他們一個嘗試:

<?php 

$string = '<?xml version="1.0" ?> 
<Public Transport Rules> 
    <PublicTransport id="0"> 
     <Issued>null</Issued> 
     <Files>&lt;localfile&gt; 
        &lt;location&gt;Citybus&lt;/location&gt; 
        &lt;format&gt;Events&lt;/format&gt; 
      &lt;/localfile&gt; 
     </Files> 
    </PublicTransport> 
</Public>'; 

$dom = new DOMDocument; 
libxml_use_internal_errors(TRUE); 
$dom->loadHTML($string); 
libxml_use_internal_errors(FALSE); 
$dom->formatOutput = TRUE; 

echo '::: Original XML :::' . PHP_EOL; 
echo $string . PHP_EOL; 
echo PHP_EOL; 

echo '::: Fixed XML :::' . PHP_EOL; 
if(version_compare(PHP_VERSION, '5.3.6', '>=')){ 
    $body = $dom->documentElement->firstChild; 
    if($body->hasChildNodes()){ 
     foreach($body->childNodes as $node){ 
      echo $dom->saveHTML($node); 
     } 
    } 
}else{ 
    $body = $dom->getElementsByTagName('body')->item(0); 
    if($body->hasChildNodes()){ 
     foreach($body->childNodes as $node){ 
      echo $dom->saveHTML($node); 
     } 
    } 
} 
echo PHP_EOL; 

...打印此:

::: Original XML ::: 
<?xml version="1.0" ?> 
<Public Transport Rules> 
    <PublicTransport id="0"> 
     <Issued>null</Issued> 
     <Files>&lt;localfile&gt; 
        &lt;location&gt;Citybus&lt;/location&gt; 
        &lt;format&gt;Events&lt;/format&gt; 
      &lt;/localfile&gt; 
     </Files> 
    </PublicTransport> 
</Public> 

::: Fixed XML ::: 
<public transport rules><publictransport id="0"><issued>null</issued><files>&lt;localfile&gt; 
        &lt;location&gt;Citybus&lt;/location&gt; 
        &lt;format&gt;Events&lt;/format&gt; 
      &lt;/localfile&gt; 
     </files></publictransport></public> 

有沒有辦法知道什麼都會丟掉在這個過程中,我們首先處理的是無效數據。

無論如何,你總是可以自動使用PHP編輯每一個有問題的文件。您的文件可能不是XML,但他們確實串;-)

+0

謝謝! :D我所需要的只是能夠移動數據,這些數據對我來說不是必需的,並且能夠解析XML文件中的其他內容。 – demenzia 2013-03-28 05:19:29

2

如果能與具有空間的標籤,整齊是一個不錯的選擇,因爲它適用於XML的重命名活,太:

$xml = simplexml_load_string(
    tidy_repair_string($string, ['input-xml' => 1]) 
); 

echo "SimpleXML::asXML():\n", $xml->asXML(), "\n\n"; 

它重命名的標籤,並創建屬性:

SimpleXML::asXML(): 
<?xml version="1.0"?> 
<Public Transport="" Rules=""> 
<PublicTransport id="0"> 
<Issued>null</Issued> 
<Files>&lt;localfile&gt; &lt;location&gt;Citybus&lt;/location&gt; 
&lt;format&gt;Events&lt;/format&gt; &lt;/localfile&gt;</Files> 
</PublicTransport> 
</Public> 

還有壓痕等,在這裏一個完整的例子更多的選擇:

<?php 
/** 
* How to parse XML files with errors using Simplexml in PHP? 
* 
* @link http://stackoverflow.com/q/15620492/367456 
*/ 

$string = '<?xml version="1.0" ?> 
<Public Transport Rules> 
    <PublicTransport id="0"> 
     <Issued>null</Issued> 
     <Files>&lt;localfile&gt; 
        &lt;location&gt;Citybus&lt;/location&gt; 
        &lt;format&gt;Events&lt;/format&gt; 
      &lt;/localfile&gt; 
     </Files> 
    </PublicTransport> 
</Public Transport Rules>'; 

echo "Broken:\n", $string, "\n\n"; 

$fixed = tidy_repair_string($string, ['input-xml' => 1, 'output-xml' => 1, 'indent' => 1]); 

echo "Fixed:\n", $fixed, "\n\n"; 


$xml = simplexml_load_string(tidy_repair_string($string, ['input-xml' => 1])); 

echo "SimpleXML::asXML():\n", $xml->asXML(), "\n\n"; 

輸出:因此

Broken: 
<?xml version="1.0" ?> 
<Public Transport Rules> 
    <PublicTransport id="0"> 
     <Issued>null</Issued> 
     <Files>&lt;localfile&gt; 
        &lt;location&gt;Citybus&lt;/location&gt; 
        &lt;format&gt;Events&lt;/format&gt; 
      &lt;/localfile&gt; 
     </Files> 
    </PublicTransport> 
</Public Transport Rules> 

Fixed: 
<?xml version="1.0"?> 
<Public Transport="" Rules=""> 
    <PublicTransport id="0"> 
    <Issued>null</Issued> 
    <Files>&lt;localfile&gt; 
    &lt;location&gt;Citybus&lt;/location&gt; 
    &lt;format&gt;Events&lt;/format&gt; &lt;/localfile&gt;</Files> 
    </PublicTransport> 
</Public> 

SimpleXML::asXML(): 
<?xml version="1.0"?> 
<Public Transport="" Rules=""> 
<PublicTransport id="0"> 
<Issued>null</Issued> 
<Files>&lt;localfile&gt; &lt;location&gt;Citybus&lt;/location&gt; 
&lt;format&gt;Events&lt;/format&gt; &lt;/localfile&gt;</Files> 
</PublicTransport> 
</Public>