0

PHP SimpleXML を学習していますが、いくつか質問があります。仕事のイントラネットで Web からコードを取得するために遊んでいます。コードはいつでも変更される可能性があるため、可能な限り汎用コードが必要です。この例では、div タグとそのすべての子を選択します。

...
  <div class="cabTabs">
      <ul>
          <li><a href="/link1">Info1</a></li>
          <li><a href="/link2">Info2</a></li>
          <li><a href="/link3">Info3</a></li>
      </ul>
  </div>
...


//Get all web content:
$b = new sfWebBrowser(); //using symfony 1.4.17 sfWebBrower to get a SimpleXML object.
$b->get('http://intranetwebexample'); //returns a sfWebBrower object.
$xml = $b->getResponseXML(); //returns a SimpleXMLElement

//[Eclipse xdebug Watch - $xml]
"$xml"    SimpleXMLElement     
  @attributes Array [3]   
  head    SimpleXMLElement    
  body    SimpleXMLElement


//Get the div class="cabTabs".
$result = $xml->xpath('//descendant::div[@class="cabTabs"]'); 

//[Eclipse xdebug Watch - $result]
"$result" Array [1]   
  0   SimpleXMLElement    
      @attributes Array [1]   
          class   cabTabs 
      ul  SimpleXMLElement    
          li  Array [6]

質問:

  1. 子孫の使用:: 接頭辞:
    他のスタックオーバーフローのトピックで、子孫:: 接頭辞が推奨されないことを読みました。タグとそのすべてのコンテンツを選択するには、どうすればよいですか? 上記のコードを使用していますが、それが正しい方法であるかどうかはわかりません。

  2. Eclipse xdebug 変数をチェックするいくつかの質問 ウォッチ:

2.1 時々、SimpleXML ツリーを 1 つまたは複数のレベル以上展開できないことがあります。上記の例では、以下の「li」ノードにアクセス/表示できず、その子が表示されません。
SimpleXML オブジェクトを使用した xdebug デバッガーの制限でしょうか、それとも Eclipse Watch の制限でしょうか?
通常のループ foreach($ul->li as $li) で親にアクセスすると、「li」ノードを完全に展開/表示できます。
ただし、重大なバグではありません。直接確認して、適切なフォーラムで報告するのが最適だと思います。

2.2 $xml->xpath の結果コードがまったくわからない:
Eclipse Watch を見ると、"div" タグは 0 インデックス キーに変換されていますが、"ul" と "li" はタグには元の名前がありましたが、なぜですか?

2.3ジェネリックコードでxpathコンテンツにアクセス/ループする方法:
次の非ジェネリックコードを使用してアクセスします:

foreach ($result as $record) {        
    foreach($record->ul as $ul) { 
        foreach($ul->li as $li) {
            foreach($li->a as $a) {
                echo ' ' . $a->name;
            }
        }
    }
}

上記のコードは機能しますが、正しいタグ名を記述した場合に限られます。(->ul, ->li, ->a..)
毎回子の名前を指定せずにすべてのコンテンツをループする一般的な方法は何ですか? (->ul、->li、->a..)
また、正しい方法でない限り、配列に変換する必要はありません。
私は children() プロパティを試してみましたが、うまくいきません。その行で停止してクラッシュします: foreach ($result->children() as $ul)

私の質問を読んでくれてありがとう。どんな助けも大歓迎です :)

システム情報:
symfony 1.4.17 with sfWebBrowserPlugin, cURL daapter.
cURL サポートが有効になっている PHP 5.4.0、cURL 情報 7.24.0

4

3 に答える 3

1
  1. 自分で使ったことがないからわからない

  2. 私は通常Zend Debugを使用していることを知りません-しかし、とにかくあなたの質問を理解していません...私はあなたがいくつかの単語を省略したと思います:-)

2.1 おそらく xdebug/eclipse。設定を確認すると、メモリの管理に役立つように再帰の量を制限する設定がある可能性があります。

2.2SimpleXML::xpath一致したノードの配列を常に返します。そのため、結果として整数インデックス配列が得られます。そのため、すべてのタグ//someelementの配列を取得します。someelementその後、 のような通常の方法でその子孫にアクセスできます$someelement->itschildelement

2.3$result->children()は、一般的な意味で物事を理解するための良い方法です。Xdebug がクラッシュしている場合、それは単なる xdebug です。オフにするか、無視するか、別のデバッガーを見つけてください:-) Xdebugは単なるツールですが、実装方法を指示するべきではありません。

于 2012-10-30T12:32:09.697 に答える
0

魅力のように働きました。

ここでは、ノードとサブノードのすべての属性で部分文字列を再帰的に検索し、見つかった完全な文字列を返す完全な関数を追加しています。

私の場合、href= のようないくつかの値や、その他の動的に生成されたタグ値を検索するのに最適です。また、上で説明したことの実装も示しています。おそらく改善され、より安全なチェックが追加される可能性があります。

/* public function bSimpleXMLfindfullstringwithsubstring($node, $sSearchforsubstring, &$sFullstringfound, &$bfoundsubstring)
 * Recursive function to search for the first substring in a list of SimpleXML objects, looking in all its children, in all their attributes.
 * Returns true if the substring has been found.
 * Parameter return:
 *   $sFullstringfound: returns the full string where the substring has been found.
 *   $bfoundsubstring: returns true if the substring has been found.
*/

public function bSimpleXMLfindfullstringwithsubstring($node, $sSearchforsubstring, &$sFullstringfound, &$bfoundsubstring=false)
{
  $bRet = false; 
  if ((isset($node) && ($bfoundsubstring == false)))
  {
      //If the node has attributes
      if ($node->attributes()->count() > 0)
      {
          //Search the string in all the elements of the current SimpleXML object.
          foreach ($node->attributes() AS $name => $attribute)  //[$name = class , (string)$attribute = cabTabs, $attribute = SimpleXML object]
          {
              //(Take care of charset if necessary).
              if (stripos((string)$attribute, $sSearchforsubstring) !== false)
              {
                  //substring found in one of the attributes.
                  $sFullstringfound = (string)$attribute;
                  $bfoundsubstring = true;
                  $bRet = true;
                  break;
              }
          }
      }

      //If the node has childrens (subnodes)
      if (($node->count() > 0) && ($bfoundsubstring == false))
      {
          foreach ($node->children() as $nodechildren)
          {
              if ($bfoundsubstring == false)
              {
                  //Search in the next children.
                  self::bSimpleXMLfindfullstringwithsubstring($nodechildren, $sSearchforsubstring, $sFullstringfound, $bfoundsubstring);
              }
              else
              {
                  break;
              }
          }
      }
  }
  return $bRet;
}

呼び方:

$b = new sfWebBrowser();
$b->get('http://www.example.com/example.html');
$xml = $b->getResponseXMLfixed();     
$result = $xml->xpath('//descendant::div[@class="cabTabs"]'); //example

$sFullString = "";
$bfoundsubstring = false;
foreach ($result as $record)
{
  self::bSimpleXMLfindfullstringwithsubstring($record, "/substring/tosearch", $sFullString, $bfoundsubstring);
}
于 2012-10-30T16:48:31.210 に答える
0

問題 2.2 と 2.3 を完全に理解できたと思います。

あなたが説明したように、そのxpathは配列[1]を返しているので、SimpleXMLオブジェクトではありません。(私は少しばかです笑)。

説明したように、解決策は簡単です。配列の要素の数を数え、要素にループしてから、SimpleXMLオブジェクトの場合はchildrenプロパティを使用して再度ループします。以下に正しいコードを追加します。

また、本当の問題を推測するために、Eclipse Watch または xdebug のポイント 1 の問題をフォーラムに送信します。

ありがとうprodigitalson、非常に有用な答え:)

于 2012-10-30T13:04:23.130 に答える