2013-03-25 4 views
2

PHP에서 XML 구문 분석과 함께 simplexml을 사용하지만 구문 분석에 필요한 일부 파일에 오류가 있음을 발견했습니다. 물론, 모든 문제가있는 파일을 수동으로 편집 할 수는 있지만, 약 10000 개 이상의 파일에서 영원히 걸릴 것입니다.PHP에서 Simplexml을 사용하여 오류가있는 XML 파일을 구문 분석하는 방법은 무엇입니까?

오케이, 오류에 대해. 브라우저에서 XML 파일을 열려고하면이 메시지가 나타납니다 :

Specification mandate value for attribute error

경고 : simplexml_load_string() : 엔티티 : 2 호선 : 파서 ​​오류 :의 속성 검사에 관한 규정의 위임 값입니다. ..

나는 발견했다. 태그는 에러 유발된다 (여기를 : 전송 대신 검사의 ) 태그 내의

<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

+0

내 유일한 해결책은 모든 단일 문제 파일을 변경하는 것입니다. – demenzia

답변

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

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> 
관련 문제