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

PHPのDOM操作で困っています。
次のようなHTML、PHPコードで、<li>要素が"foo"の場合に、その"children"配下をremoveChildしたいのですが、"foo"だけでなく"hoge"配下の"children"まで削除されてしまいます。
どうすれば意図したような結果が得られますか?

[DOM操作したいHTML]
<ul>
<li class="item-1"><a href="http://example.com/hoge">hoge</a>
<ul class="children">
<li class="item-2"><a href="http://example.com/hoge/001">hogehoge</a></li>
<li class="item-3"><a href="http://example.com/hoge/002">hogehogehoge</a></li>
</ul>
</li>
<li class="item-4"><a href="http://example.com/foo">foo</a>
<ul class="children">
<li class="cat-item-5"><a href="http://example.com/foo/001">foofoo</a></li>
<li class="cat-item-6"><a href="http://example.com/foo/002">foo</a></li>
</ul>
</li>
</ul>

[PHPコード]
$doc = new DOMDocument();
$doc->loadXML($temp);
echo $doc->saveXML($doc);
$a = $doc->getElementsByTagName("a");
for($_cnt = 0; $_cnt < $a->length; $_cnt++){
$target = $a->item($_cnt);
if($target->parentNode->parentNode->getAttribute("class") == "children"){
if(trim( $a->item($_cnt - 1)->nodeValue ) != "foo"){
$target->parentNode->parentNode->parentNode->removeChild( $target->parentNode->parentNode );
}
}
}
echo $doc->saveXML($doc);

●質問者: P-mako
●カテゴリ:インターネット ウェブ制作
✍キーワード:Class DOC DOM echo hoge
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● tdoi
●30ポイント

やりたいことがよく分かっていませんが、ソースから判断すると、

aタグの中身がfooでかつ、そのaタグを含むliタグを含むulタグのclass属性がchildrenであれば、そのulタグ以下のノードを削除するということでよいですか?


それであれば、以下のtypoだけではないでしょうか?

if(trim( $a->item($_cnt - 1)->nodeValue ) != "foo"){

が、

if(trim( $a->item($_cnt - 1)->nodeValue ) == "foo"){

ですよね?

コメントあけてもらえれば、補足します。


何かの参考になれば。

http://dummy

◎質問者からの返答

ご指摘ありがとうございます。

たしかに質問文には誤りがありました。

ただし、これは質問文をシンプルにするためのリライト時に、

修正し忘れた箇所で、意図した結果はやはり得られない状態です。

正確に訂正しますと、children配下をremoveしようと試みている

コードはご指摘の条件文のelseに書いています。


2 ● tdoi
●40ポイント ベストアンサー

まだ、目的が見えていないので、はずしているかもしれませんが、これが、望む挙動でしょうか?

$doc = new DOMDocument();
$doc->loadXML($temp);
echo $doc->saveXML($doc);
$a = $doc->getElementsByTagName("a");
for($_cnt = 0; $_cnt < $a->length; $_cnt++){
 $anchor = $a->item($_cnt);
 if (trim($anchor->nodeValue) == "foo") {
$target = $anchor->parentNode;
$children = $target->childNodes;
for ($i = 0; $i < $children->length; ++$i) {
 $node = $children->item($i);
 if ($node->nodeName == 'ul' && $node->getAttribute("class") == "children") {
$target->removeChild($node);
 }
}
 }
 }
echo $doc->saveXML($doc);

もし、違うようであれば、期待する結果を示してもらえますか?

http://dummy


3 ● suenaga3
●10ポイント

今は手元に環境がないのでちょっと確認できないのですが、

ループ文がちょっと危険な感じがします。

提示された例だと、Aタグが6個あるので、6回ループしますが、

6回目のループ時に(5個目、6個目のAタグが消えた後に)

$a->item(4)、および $a->item(5) を参照することになります。

ですがその時、すでにそのタグオブジェクトがないので、動作が

どうなるのか分かりません。

そのあたりで怪しい挙動をしているのかもしれません。

それが原因だとした場合には、

ループを抜けるまでは削除を行わずに配列で確保して、後から

改めて削除するというのはどうでしょう。

http://dummy

◎質問者からの返答

ご指摘ありがとうございます。

たしかにそういう観点も考慮したほうが良いですね。

関連質問


●質問をもっと探す●



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