2010-12-29 11 views
0

XPathを使い始めるだけで、PHPのSimpleXMLオブジェクトで実装されています。今私はを使用してSimpleXMLオブジェクトの配列を作成しています。zuqという接頭辞が与えられたドキュメントにあります。しかし、私はSimpleXMLオブジェクトが名前空間に関係なくすべての子孫を参照するようにしたいと思います。私は//child::zuq:*を使ってみましたが、作成するSimpleXMLツリーは完全ではないようです。名前空間要素のすべての子のXPath文字列

キャプチャされるオブジェクトは、zuqなど、名前空間に関係なくすべての子孫要素を含む、ドキュメント全体のzuq名前空間のすべての最上位オブジェクトである必要があります。

TL; DR:私は各SimpleXMLルートオブジェクトは、指定された名前空間の最上位レベルの文書要素が与えられた文書からSimpleXMLオブジェクトツリーを作成するにはどうすればよい(例えばzuq)かかわらず、前記要素のすべての子孫を含みます子孫の名前空間? XPathは必須条件ではありませんが、私の読書に基づいて最良の選択肢と思われます。


test.htmlという

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:zuq="http://localhost/zuq"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Untitled Document</title> 
</head> 

<body> 
    <h1>Heading</h1> 
    <p>Paragraph</p> 
    <zuq:region name="myRegion"> 
     <div class="myClass"> 
      <h1><zuq:data name="myDataHeading" /></h1> 
      <p> 
       <zuq:data name="myDataParagraph"> 
        <zuq:format type="trim"> 
         <zuq:param name="length" value="200" /> 
         <zuq:param name="append"> 
          <span class="paragraphTrimOverflow">...</span> 
         </zuq:param> 
        </zuq:format> 
       </zuq:data> 
      </p> 
     </div> 
    </zuq:region> 
</body> 
</html> 

$sxml = simplexml_load_file('test.html'); 
$sxml_zuq = $sxml->xpath('//zuq:*/descendant-or-self::node()'); 
print_r($sxml_zuq); 

が生成されます

Array 
(
[0] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => myRegion 
      ) 

     [div] => SimpleXMLElement Object 
      (
       [@attributes] => Array 
        (
         [class] => myClass 
        ) 

       [h1] => SimpleXMLElement Object //I don't know why these don't contain their zuq descendants 
        (
        ) 

       [p] => SimpleXMLElement Object 
        (
        ) 

      ) 

    ) 

[1] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => myRegion 
      ) 

     [div] => SimpleXMLElement Object 
      (
       [@attributes] => Array 
        (
         [class] => myClass 
        ) 

       [h1] => SimpleXMLElement Object 
        (
        ) 

       [p] => SimpleXMLElement Object 
        (
        ) 

      ) 

    ) 

[2] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [class] => myClass 
      ) 

     [h1] => SimpleXMLElement Object 
      (
      ) 

     [p] => SimpleXMLElement Object 
      (
      ) 

    ) 

[3] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [class] => myClass 
      ) 

     [h1] => SimpleXMLElement Object 
      (
      ) 

     [p] => SimpleXMLElement Object 
      (
      ) 

    ) 

[4] => SimpleXMLElement Object 
    (
    ) 

[5] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => myDataHeading 
      ) 

    ) 

[6] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [class] => myClass 
      ) 

     [h1] => SimpleXMLElement Object 
      (
      ) 

     [p] => SimpleXMLElement Object 
      (
      ) 

    ) 

[7] => SimpleXMLElement Object 
    (
    ) 

[8] => SimpleXMLElement Object 
    (
    ) 

[9] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => myDataParagraph 
      ) 

    ) 

[10] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => myDataParagraph 
      ) 

    ) 

[11] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [type] => trim 
      ) 

    ) 

[12] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [type] => trim 
      ) 

    ) 

[13] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => length 
       [value] => 200 
      ) 

    ) 

[14] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [type] => trim 
      ) 

    ) 

[15] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => append 
      ) 

     [span] => ... 
    ) 

[16] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => append 
      ) 

     [span] => ... 
    ) 

[17] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [class] => paragraphTrimOverflow 
      ) 

     [0] => ... 
    ) 

[18] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [class] => paragraphTrimOverflow 
      ) 

     [0] => ... 
    ) 

[19] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => append 
      ) 

     [span] => ... 
    ) 

[20] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [type] => trim 
      ) 

    ) 

[21] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => myDataParagraph 
      ) 

    ) 

[22] => SimpleXMLElement Object 
    (
    ) 

[23] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [class] => myClass 
      ) 

     [h1] => SimpleXMLElement Object 
      (
      ) 

     [p] => SimpleXMLElement Object 
      (
      ) 

    ) 

[24] => SimpleXMLElement Object 
    (
     [@attributes] => Array 
      (
       [name] => myRegion 
      ) 

     [div] => SimpleXMLElement Object 
      (
       [@attributes] => Array 
        (
         [class] => myClass 
        ) 

       [h1] => SimpleXMLElement Object 
        (
        ) 

       [p] => SimpleXMLElement Object 
        (
        ) 

      ) 

    ) 

) 
+2

xmlを含めないようにしてください。そうしないと、すぐにこの質問に回答します。 – ajreal

+0

@ajreal;ルルツ。良いことも、答えは過大評価されています:) – Dan

答えて

2

print_rステートメントの出力を信頼しないでください...空のオブジェクトを表示しているようですが、テストでは実際にはまだそこにあります。

print_r($sxml_zuq[0]->div->h1); 

私はこの出力を得る::私はその後、このようなコマンドしようとした場合

$sxml = simplexml_load_file('test.html'); 
$sxml_zuq = $sxml->xpath('//zuq:*/descendant-or-self::node()'); 

:たとえば、上記のコードで始まる

SimpleXMLElement Object 
(
) 

空のようですが、右?私はこのように見えるようにコマンドを変更した場合でも:

echo $sxml_zuq[0]->div->h1->asXML(); 

を私は名前空間の子供で結果ツリーを取得:

<h1><zuq:data name="myDataHeading"/></h1> 

私はこれがなぜ100%わかりません。おそらく、simplexmlオブジェクトをフラット化し、ネームスペースを適切に処理しないprint_rステートメントと関係があるでしょう。しかし、xpath呼び出しから返されるsimplexmlオブジェクト自体を保持すると、すべての子が保持されます。

xpath自体に関しては、おそらく "子孫または自己"軸が必要ないでしょう。これはトップレベルのzuq要素だけでなく、すべての子要素と一致して作成するためですあなたが実際に返そうとしているよりも大きな配列(あなたが求めているものを誤解している場合を除きます)。

$sxml_zuq = $sxml->xpath('//zuq:*[not(ancestor::zuq:*)]'); 

次に、zuq名前空間要素のトップレベルの配列のみが返されます。 (あなたの例のXMLはそのようなトップレベルの要素を1つしか持たないが、実際のデータはそのレベルでいくつかの兄弟を持つかもしれない)。あなたは、このプロセスを繰り返しますが、トップレベルの検索(または任意)を行う場合の要素を

foreach ($sxml_zuq as $zuq_node) { 
    echo ($zuq_node->asXML()); 
} 

物事は少しトリッキー取得する:あなたは、このようなこれらのトップレベル要素のそれぞれの内容をキャプチャすることができますデフォルトネームスペース。 registerNamespace関数を使用して、デフォルトの名前空間に一時的な接頭辞を与え、その上でxpath検索を行う必要があります。

+0

あなたは絶対に正しいです** jlmcdonald **;ここでスレッドに戻る前に、 'var_dump'、' print_r'などの変形は 'SimpleXML'を扱うとき不正なオブジェクトツリーをダンプする傾向があり、名前空間の要素が原因と思われます。また、XPathの文字列の提案は、魅力のように機能します。私は 'asXML()'を将来の 'SimpleXML'の完全性検査に使うことを確実にします。再度、感謝します! – Dan

+0

+1 '/ zuq:* [not(ancestor :: zuq:*)]'に対して、これはその名前空間の最も外側の要素を正しく選択します。 –

1

私はあなたが//zuq:*/descendant-or-self::*を探していると思います。これにより、ルートがすべてzuqの名前空間接頭辞を持つすべてのサブツリーになります。

この動作はSimpleXMLの成果物のようです(XPath仕様ではXPathクエリ出力のツリーは処理されず、別個のノードのみが処理されます)。あなたはおそらく

//zuq:*[not(ancestor::zuq:*)]/descendant-or-self::*

祖先のようなものを使用してそれを解決することができます[...]条件が真である祖先が存在するかどうかをチェック - つまりzuq接頭辞を持つ祖先があるかどうか。だからあなたはzuq:祖先を持たない根:祖先だけを得るべきです。

+0

ありがとうzeuxcg;しかし、作成された 'SimpleXML'オブジェクトは同じように見えます。私は '子孫 - または - 自己について'を読んでいて、それも答えだと思った。 'print_r'は同じようにダンプします。私はそれで遊ぶよ。その他の提案や方法は? – Dan

+0

不完全なことはどういう意味ですか?テキストノードがない場合は、*の代わりにdescendant-or-self :: node()でなければなりません。 – zeuxcg

+0

詳細については、ツリーには 'zuq'名前空間のルート要素があり、この場合はXHTMLドキュメントの' p'や 'div'のような' zuq'名前空間からの要素を含んでいますが、XPathがヒットすると'zuq'名前空間の子孫であり、' SimpleXML'オブジェクトツリーに含まれず、代わりに新しい配列要素を作成します。私はそれに応じて質問を更新しました。 – Dan

関連する問題