19

これはJavascriptで有効なXPathです。

id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]

そして、これはDOMXPath-> query()で使用される有効なPHPXPathになりました。

//*[@id="priceInfo"]//div[@class="standardProdPricingGroup"]//span[1]
  1. この変換をすでに実行しているライブラリまたはカスタムコンポーネントを知っていますか?
  2. 2つの構文の違いをリストした利用可能なドキュメントを知っていますか?

私の主な関心事は、多くの違いがある可能性があることです。私はこれらの違いを特定しようとしていますが、これらを特定するのに問題があります。

質問は別の言い方をすることもできます。Javascriptはさまざまな有効なXPath形式を持つことができるため、PHPで動作するようにそれらを正規化する方法。

更新の1つには、この定義を含む有効なDTDがある場合、id()関数が有効なXPathであることが記載されています。私には入力DTDに対する力がありません。特定のDTDなしで機能するソリューションを見つける方法があれば、それは素晴らしいことです。

アップデート:

アルゴリズムを使用して、最初の形式を2番目の形式に変換したいと思います。私の入力は最初のものであり、2番目のものではありません。これを変更することはできません。

@NisonMaëlが指摘したように、2番目の形式は次のように有効なJavascript XPathです。http://jsbin.com/elatum/2/edit残念ながら、これはJavascriptXPathの「断片化」の問題に追加されます。

@salatheは、文書化された入力に有効なDTDがある場合、有効なJavascript XPathクエリがPHPで正常に機能することを指摘しました(@Dimitre Novatchevはコメントでこれについて言及しましたが、重要性を見落としていました)。残念ながら、入力DTDを制御できないため、これを克服する方法を調査するか、有効なDTDがなくても機能するソリューションを見つける必要があります。

4

3 に答える 3

7

Salatheが実際に同じように答えたのを見るだけですが、あなたのコメントを考慮に入れて、これをもう少し強調します。

DTDを指定する必要はありません。DOMDocument::loadHTMLまたは関数を使用している限りDOMDocument::loadHTMLFile、HTMLid属性は実際にはxpathid()関数に登録されます。http://jsbin.com/elatum/2/editにあるデモHTMLを使用すると、ドキュメントをロードするときにエラーが発生することもあります。

警告:DOMDocument :: loadHTMLFile():IDpriceInfoはすでに...で定義されています

これは、重複についてうめき声を上げているため、これが真のID属性であることをすでに示しています。関連するサンプルコードは次のようになります。

$xpath = 'id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]';

$doc = new DOMDocument();
$doc->loadHTMLFile(__DIR__ . '/../data/file-11796340.html');
$xp = new DOMXPath($doc);

$r = $xp->query($xpath);
echo $xpath, "\n";
echo $r ? $r->length : 0, ' elements found', "\n";
if (!$r) return;
foreach($r as $node) {
    echo " - ", $node->nodeValue, "\n";
}

出力は次のとおりです。

id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]
1 elements found
 - hello

さらに制御が必要な場合は、最初にxpathを実行して、すべてのHTMLid属性をxpathのIDとしてマークします。

$r = $xp->query("//*[@id]");
if ($r) foreach($r as $node) {
    $node->setIdAttribute('id', true);
}

その後、関数で同じxpathを使用でき、id()変更する必要はありません。

于 2012-08-05T19:19:31.797 に答える
0

あなたはあなたの表現の始めにただ翻訳id("...")することができませんか?//*[@id="..."][1]

たとえば、id(...)式に括弧がないと想定できる場合は、次のようになります。

$queryRewritten =   preg_replace('/^id\(([^\)]+)\)/','//*[@id=$1][1]',$query);

サンプルコード

編集:置換を修正しました。id()は式の最初である必要があります

于 2012-08-07T13:23:41.317 に答える
0

これは完全な答えではありませんが、コメントとして入れるには大きすぎるので、少し役立つかもしれません。

入力XMLを制御できる場合は、DTDを使用して属性を宣言する代わりに、属性の前に。idを付けることで、XMLドキュメント自体で明示的に宣言できます。idxml:

たとえば、次のXMLがある場合

<foo id="x27"/>

に変更しました

<foo xml:id="x27"/>

その場合、id()関数は、その属性を、名前が付いた属性としてだけでなく、正式なXMLid型として認識しますid

この「トリック」がSaxonプロセッサで機能することは知っていますが、PHPで試したことがないことを認めなければなりません。

W3C xml:id

于 2012-08-08T23:46:09.837 に答える