人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

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のプログラム:
http://1811way.com/work008/test026php.txt
ソースを表示させるために拡張子txtをつけています。
includeするhtml:
http://1811way.com/work008/sample05html.txt

私のやっているlocal開発環境
Windows8.0
Apache2.4
php5.6.2

以上、よろしくお願いします。

●質問者: kohhi
●カテゴリ:ウェブ制作
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● rouge_2008
●200ポイント ベストアンサー

1.ulタグの右側の文字を表示させたいのですが。
find( 'ul' )だと、ulの中のliを表示させてしまいます。

指定したHTMLタグ内にあるHTMLタグやテキストはすべて取得されます。
「ul」のように「li」が入れ子になっている場合、「ul」の内容として「li」の内容もすべて含まれます。

<div id="wrap">
 <div id="header">
 ヘッダー
 </div>
 <div id="content">
 コンテンツ
 </div>
 <div id="sidebar">
 サイドバー
 </div>
 <div id="footer">
 フッター
 </div>
</div>

※上記のように外側(※上の階層)の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
http://php.net/manual/ja/language.oop5.properties.php

※「Simple HTML DOM Parser」で使用できるプロパティとメソッドについては、マニュアルとAPI Referenceを参照してください。

・API Reference
http://simplehtmldom.sourceforge.net/manual_api.htm
※以下に「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
http://simplehtmldom.sourceforge.net/manual.htm#frag_find_nested

// Find all <li> in <ul> 
foreach($html->find('ul') as $ul) 
{
 foreach($ul->find('li') as $li) 
 {
 // do something...
 }
}

// Find first <li> in first <ul> 
$e = $html->find('ul', 0)->find('li', 0);

指定した要素「$html->find('ul')」内のすべてのulおよびli要素にアクセスする場合は、前者のように「foreach()」を利用します。(※ループの中でさらにループさせます。)
任意の要素にアクセスする場合は、後者のようにインデックスを指定します。(※1番目は「0」です。)


W3CのHTMLの仕様に沿っていないHTMLでしたので、リストのコード例を以下のように修正します。(※処理の為のコードが複雑にならないためにも、仕様に沿ったHTMLで試してみてください。)

【HTML例】

<ul id="right">
 <li><h2>ul 1階層目のli その1 見出し用?</h2>
 <ul>
 <li><h3>ul 2階層目のli その1 見出し用?</h3>
 <ul>
 <li>ul 2階層目のli その2 項目1</li>
 <li><h4>ul 3階層目のli その1 見出し用?</h4>
 <ul>
 <li>ul 3階層目のli その2 項目1</li>
 <li>ul 3階層目のli その3 項目2</li>
 </ul>
 </li>
 </ul>
 </li>
 </ul>
 </li>
</ul>

・ul 要素
https://developer.mozilla.org/ja/docs/Web/HTML/Element/ul
※「入れ子状に配置されたリスト」参照


【PHP例】(※任意に指定したidで取得します。)

foreach ($html->find('ul#right') as $ul) {
 echo "<h1>入れ子リスト elements.</h1>\n";
 $i = 1;
 echo "<h2>ブラウザ表示確認</h2>";
 echo "ulリストプレビュー表示" . $ul . "<br>\n";
 echo "以下、結果確認(li内テキスト)<br>\n";
 foreach ($ul->find('li') as $li) {
 if(preg_match('#^(.+?)(<ul>.+)?$#s', $li->innertext, $matches)) {
 $text = "<div style='border:1px dotted navy; padding: 6px;'>";
 echo $text . $i . " is " . $matches[1] . "</div>\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」プロパティを利用してみてください。


kohhiさんのコメント
>※上記のように外側(※上の階層)のdiv要素(※id「wrap」のdiv)を取得した場合、 >idが「header」「content」「sidebar」「footer」の >div要素もすべて含まれます。 >指定した要素「$html->find('ul')」内のすべてのulおよびli要素にアクセスする場合は、 >前者のように「foreach()」を利用します。(※ループの中でさらにループさせます。) かなり深い入れ子になっているul,liもループ処理で取り出せるんですね。 じっくりやってみます。 >「・How to find HTML elements? > Nested selectors」 の応用で、入れ子の深いものをやってみるつもりです。 「Notice: Trying to get property ・・」は、 いつも出てくるエラーメッセージで、 僕にとっては大きなヒントになり、勉強になりました。 「->」(矢印演算子)の実践的な意味がわかりかけてきたように思います。 「Simple HTML DOM Parser」で使用できるプロパティとメソッドについては、マニュアルとAPI Referenceを・・」 これが基本ですね。じっくり読みます。 >PHP例】(※任意に指定したidで取得します。) >※入れ子になっているので、上の階層の「li」の内容として下層にある >「ul」の「li」の内容も含まれる為、 >正規表現で検索して必要な部分だけ取得しています。 サンプル修正、プログラムまで書いていただいて、ありがとうございました。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ