2

そのため、PHPのXML解析でsimplexmlを使用しましたが、解析する必要のあるファイルの一部にエラーが含まれていることがわかりました。もちろん、問題のあるすべてのファイルを手動で編集することもできますが、約10000以上のファイルでは、それは永遠にかかります。

さて、エラーについてです。ブラウザでXMLファイルを開こうとすると、次のメッセージが表示されます。

属性エラーの仕様義務値

警告: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あなたがブラウザページで読んだものに開かれているようです。

しばらくの間、この問題で立ち往生しています。何かアドバイスをいただければ幸いです。

ありがとう!

4

2 に答える 2

2

スペースを含むタグの名前を変更しても問題が解決しない場合は、XMLでも機能するため、tidyを使用することをお勧めします。

$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>
于 2013-11-02T13:34:06.877 に答える
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ではないかもしれませんが、実際には文字列です;-)

于 2013-03-25T17:14:31.167 に答える