1

問題があります。で名前空間を含む HTML スニペットをロードしたいDOMDocument

<div class="something-first">
    <div class="something-child something-good another something-great">
        <my:text value="huhu">
    </div>
</div>

しかし、名前空間を保持する方法がわかりません。でロードしようとしましloadHTML()たが、HTMLには名前空間がないため、それらが削除されます。

私はそれをロードしようとしましloadXML()たが、これはうまくいきませんどちらの原因<my:text value="huhu">も正しいXMLではありません.

私が必要としているのは、loadHTML()名前空間を削除しないloadXML()メソッド、またはマークアップを検証しないメソッドです。したがって、この2つの方法の組み合わせ。

これまでの私のコード:

$html = '<div class="something-first">
    <div class="something-child something-good another something-great">
        <my:text value="huhu">
    </div>
</div>';

libxml_use_internal_errors(true);

$domDoc = new DOMDocument();
$domDoc->formatOutput = false;
$domDoc->resolveExternals = false;
$domDoc->substituteEntities = false;
$domDoc->strictErrorChecking = false;
$domDoc->validateOnParse = false;

$domDoc->loadHTML($html/*, LIBXML_NOERROR | LIBXML_NOWARNING*/);
$xpath = new DOMXPath($domDoc);
$xpath->registerNamespace ( 'my', 'http://www.example.com/' );

// -----> This results in zero nodes cause namespace gets stripped by loadHTML()
$nodes = $xpath->query('//my:*');
var_dump($nodes);

私が望むものを達成する方法はありますか?アドバイスをいただければ幸いです。

編集HTML で名前空間を保持するオプションを提供する libxml2 の拡張要求を開きました: https://bugzilla.gnome.org/show_bug.cgi?id=711670

4

2 に答える 2

2

技術的には、有効な XML や HTML (または XHTML) ではありません。HTML では名前空間付きの要素が許可されていませんが、有効な XML では空の要素が自己終了し、名前空間が登録されている必要があります。したがって、基本的に「この無効な HTML を、有効な XML ではないにもかかわらず、有効な XML として DOMDocument に処理させるにはどうすればよいですか?」と尋ねます。これは難しいことが判明し、なぜこれを可能にするために libxml を更新する必要があるのか​​ 疑問に思うかもしれません。スニペットを次のように更新すると:

$html = <<<XML
<div xmlns:my="http://www.example.com/" class="something-first">
    <div class="something-child something-good another something-great">
        <my:text value="huhu" />
    </div>
</div>
XML;

NS 登録を追加して を閉じるとmy:text、次のように問題なく動作します。

$domDoc = new DOMDocument();
$domDoc->loadXML($html);
echo $domDoc->saveXML();

名前空間が削除されていないことに注意してください。私が理解しているように、名前空間は有効な XML または HTML ではないため、取り除かれています。名前空間は xmlns を介して定義されておらず、削除されたため、XPath は名前空間でクエリを実行できません。

では、問題は次のようなものだと思います。なぜ、終わりのスラッシュを追加するのではなく、無効な XML のサポートを請願しているのですか? データが外部ソースからのものであるためですか、それとも何らかのコンテキストで空の非終了タグが有効であるためですか?

于 2013-11-08T17:15:55.323 に答える
2

まず、名前空間は XML (または XHTML) でのみ使用できます。HTML は名前空間をサポートしていません。


それが XHTML であり、xmlns 宣言がスニペットに存在する場合、以下を使用して名前空間によって要素にアクセスできますDOMDocument::getElementsByTagNameNS()

$html = <<<EOF
<div xmlns:my="http://www.example.com/" class="something-first">
    <div class="something-child something-good another something-great">
        <my:text value="huhu" />
    </div>
</div>
EOF;

$domDoc = new DOMDocument();
$domDoc->loadXML($html);
var_dump(
  // it is possible to use wildcard `*` here
  $domDoc->getElementsByTagNameNS('http://www.example.com/', '*')
);

ただし、名前空間の宣言は<html>サブノードではなくルート要素で定義されることが一般的であるため、ほとんどの場合、上記のコードは機能しません。

したがって、解決策のパート2は、宣言が存在するかどうかを確認し、そうでない場合はそれを注入することです....(これに取り組んでいます)


前述のとおり、上記のコードは XML / XHTML でのみ機能します。HTMLでそれを行う方法はまだ開いています。(以下の議論をチェックしてください)

于 2013-11-08T09:53:13.520 に答える