私の最後の質問のフォローアップで、xml ファイルに不正な形式の文字列がある場合、preg_replace_callback() を使用してコンテンツを抽出し、破損した要素を削除できます。
この関数のポイントは、xml を regex で解析することではなく (悪い考えです)、解析できない xml と解析に失敗した場所を見つけて、送信前に正しくフォーマットされていない記事にフラグを立てることができるようにすることです。アウト。これは、配信前にコンテンツをクリーニングする一連のツールの一部です。既知の不正な公開 RSS URL と内部 URL でテストして、さまざまな状況に対応できるかどうかを確認しています。コールバックは、失敗したノードの整数を返します。その後合格した場合は、記事のインデックスを報告し、DOMDocument を使用して html を修正し、再試行することができます。失敗した場合は重大として報告します。それ以外の場合は、解析中の記事の説明とコンテンツをデータベースに戻し、配信前に変更済みとしてマークします。
次に、壊れた要素を取得して DOMDocument で実行し、より適切にフォーマットして XML ファイルに戻すことができます。
ただし、以下の例で false 以外を返す方法に行き詰まっています。
サンプル XML:
<item>
<content:encoded><![CDATA[
This is the text with odd characters that are killing
simplexml_load_string() (doesn't recover) and breaking
(although recoverable) DOMDocument
]]></content:encoded>
</item>
次の PHP を使用すると、説明ノードを抽出して変換できます。
<description><![CDATA[
This is some description text with the same problem
]]></description>
に
<description>0</description>
PHP:
preg_replace_callback(
'/<description>(.*)<\/description>/', **// add msU modifiers to fix below**
'node_tidy::callback_description',
$xml
);
...
private function callback_description($matches=false) {
if(false !== $matches) {
$this->arrDescriptions[] = $matches[1];
return '<description>'.$this->indexDescriptions++.'</description>';
} else {
return false;
}
}
ただし、ノードで同じことをしようとすると、content:encoded
false が返されます。関連する関数は次のとおりです。
private function callback_content_encoded($matches=false) {
if(false !== $matches) {
$this->arrContentEncoded[] = $matches[1];
return '<content:encoded>'.$this->indexContentEncoded++.'</content:encoded>';
} else {
return false;
}
}
ストレート正規表現を使用して、それがコロンかどうかをテストするために、これを使用しました:
<?php
$string = '<content:encoded>this is some text</content:encoded>';
preg_match('/<content\:encoded>(.*)<\/content\:encoded>/',$string,$matches);
echo '<pre>';
print_r($matches);
echo '</pre>';
?>
ただし、追加の有無にかかわらず、期待される配列を出力しませんでした\:
。ここでの誤解について、誰かが私を正しい方向に向けることができますか?
どうもありがとう!
更新: @Florent で示されているように、失敗した実際の xml のサンプル スニペットを次に示します。
更新: この正規表現は、必要なコンテンツと一致します。
preg_match('/<content\:encoded>(.*)<\/content\:encoded>/msU',$string,$matches);
m および s および U 修飾子については、こちらで詳しく説明しています: http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
これらの修飾子を考慮することを怠っていました。
元の問題を含め、この正規表現によって結果が返されるようになったため、これを解決できるようになりました。