2013-03-25 82 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>