質問: simple_html_dom.phpを使った構文で、質問を2つさせてください。 1.ulタグの右側の文字を表示させたいのですが。 find( 'ul' )だと、ulの中のliを表示させてしまいます。 find( 'ul' )->text だとnon-objectと言われる。 *test26.phpの17,18,19行目(//はコメント) どうすればulの右側の文字が表示されますか。 2.test26.phpの21,22,23行目(//はコメント)ulタグの中にliタグがあるので、 if (!empty( $a->value))が正しいように思いますが、 !だと何も表示されません。逆のような気がしてしょうがありません。 ヒントとなる説明のようなものをいただけると助かります。 ソースプログラムは以下2点を見てください。 PHPのプログラム: ソースを表示させるために拡張子txtをつけています。 includeするhtml: 私のやっているlocal開発環境 Windows8.0 Apache2.4 php5.6.2 以上、よろしくお願いします。
回答: > 1.ulタグの右側の文字を表示させたいのですが。 > find( 'ul' )だと、ulの中のliを表示させてしまいます。 > > 指定したHTMLタグ内にあるHTMLタグやテキストはすべて取得されます。 「ul」のように「li」が入れ子になっている場合、「ul」の内容として「li」の内容もすべて含まれます。 ``` ヘッダー コンテンツ サイドバー フッター ``` ※上記のように外側(※上の階層)のdiv要素(※id「wrap」のdiv)を取得した場合、idが「header」「content」「sidebar」「footer」のdiv要素もすべて含まれます。 ※同じ階層にある要素は含まれませんので、idが「header」「content」「sidebar」「footer」のdiv要素の場合は、他の要素の内容は含まれません。(※任意で指定して取得した場合だけでなく、ループ処理時にも各々の要素の内容だけが含まれます。) > find( 'ul' )->text だとnon-objectと言われる。 > *test26.phpの17,18,19行目(//はコメント) > > ※オブジェクトではないものに「->」を使っているので「non-object」のNOTICEメッセージが表示されています。(※「Notice: Trying to get property of non-object in /path/... on line **」は「/path/...の**行目で、オブジェクトではない物のプロパティを取得しようと試みました」という内容です。) DOM、Element何れの場合も、「find()」でインデックスを指定しなかった場合はオブジェクトの配列を返しますので、「$a->find('ul')」の返り値は配列になります。 「->」(矢印演算子)はオブジェクトにアクセスする為の演算子ですので、配列にはアクセスできません。 オブジェクトへのアクセスについては、以下のページを参照してください。 ・PHP: プロパティ - Manual ※「Simple HTML DOM Parser」で使用できるプロパティとメソッドについては、マニュアルとAPI Referenceを参照してください。 ・API Reference ※以下に「find()」について一部抜粋します。 > DOM methods & properties > mixed find ( string $selector [, int $index] ) Find elements by the CSS selector. Returns the Nth element object if index is set, otherwise return an array of object. > > Element methods & properties > mixed find ( string $selector [, int $index] ) Find children by the CSS selector. Returns the Nth element object if index is set, otherwise, return an array of object. > > インデックスを指定した場合は任意の順番のHTML要素のオブジェクトを返しますが、それ以外の場合はオブジェクトの配列を返すとあります。 ※「file_get_html()」および「str_get_html()」の結果は、DOM(※simple_html_dom)のオブジェクトが返りますので、この取得結果に対して使用できるプロパティとメソッドは「DOM methods & properties」の表を参照してください。 DOM、Element何れの場合も、「find()」の結果はElement(※simple_html_dom_node)が返りますので、この取得結果に対して使用できるプロパティとメソッドは「Element methods & properties」の表を参照してください。 ※「find()」でインデックス指定しなかった場合はオブジェクトの配列になりますので、「foreach()」でループ処理する必要があります。 マニュアルで、ネストされた(入れ子になった)タグのアクセス例として、ちょうど「ul」「li」が例示されています。 ・How to find HTML elements? > Nested selectors > > ``` > // Find all in > foreach($html->find('ul') as $ul) > { > foreach($ul->find('li') as $li) > { > // do something... > } > } > > // Find first in first > $e = $html->find('ul', 0)->find('li', 0); > > ``` > 指定した要素「$html->find('ul')」内のすべてのulおよびli要素にアクセスする場合は、前者のように「foreach()」を利用します。(※ループの中でさらにループさせます。) 任意の要素にアクセスする場合は、後者のようにインデックスを指定します。(※1番目は「0」です。) W3CのHTMLの仕様に沿っていないHTMLでしたので、リストのコード例を以下のように修正します。(※処理の為のコードが複雑にならないためにも、仕様に沿ったHTMLで試してみてください。) 【HTML例】 ``` ul 1階層目のli その1 見出し用? ul 2階層目のli その1 見出し用? ul 2階層目のli その2 項目1 ul 3階層目のli その1 見出し用? ul 3階層目のli その2 項目1 ul 3階層目のli その3 項目2 ``` ・ul 要素 ※「入れ子状に配置されたリスト」参照 【PHP例】(※任意に指定したidで取得します。) ``` foreach ($html->find('ul#right') as $ul) { echo "入れ子リスト elements.\n"; $i = 1; echo "ブラウザ表示確認"; echo "ulリストプレビュー表示" . $ul . "\n"; echo "以下、結果確認(li内テキスト)\n"; foreach ($ul->find('li') as $li) { if(preg_match('#^(.+?)(.+)?$#s', $li->innertext, $matches)) { $text = ""; echo $text . $i . " is " . $matches[1] . "\n"; } $i++; } } ``` ※入れ子になっているので、上の階層の「li」の内容として下層にある「ul」の「li」の内容も含まれる為、正規表現で検索して必要な部分だけ取得しています。 ※「plaintext」プロパティの場合、HTMLタグが除外される為、検索の目印がなくなってしまいますから、「innertext」プロパティを使用します。 > 2.test26.phpの21,22,23行目(//はコメント)ulタグの中にliタグがあるので、 > if (!empty( $a->value))が正しいように思いますが、 > !だと何も表示されません。 > > 存在しないプロパティ「value」を指定した為に「false」が返されたようです。(※リファレンスにも記載されていません。) その為、 「$a->value」の結果は必ず「偽」になりますので、判定の内側の処理は行われません。(※指定したHTML要素が「input」等、「value」属性を持つHTMLタグの場合は、「value」に指定された値が返りますので、この場合は判定に利用できると思います。) 指定した要素の中身の有無判定には、適切な位置で「innertext」プロパティを使ってみてください。(※入れ子になっていなければ「plaintext」も使えます。) ※「text」は使用できるプロパティではありません。(※Element(simple_html_dom_node)のメソッド「text()」としては利用できるようですが、もしHTMLタグを除外した内容が必要な場合は「plaintext」プロパティを利用してみてください。