2

次のコードがあるとします。

<div class="content">
    <h3>Test</h3>
    <img src="#" alt="" />
    <p>Lorem ipsum</p>
    <p>dolor sit</p>
    <p><!-- pagebreak --></p>
    <p>amet</p>
</div>

コードをトリミングして改ページ後のすべてを削除したいが、html ロジックは保持したい ( </div>):

<div class="content">
    <h3>Test</h3>
    <img src="#" alt="" />
    <p>Lorem ipsum</p>
    <p>dolor sit</p>
</div>

ツール: Zend、通常の PHP。

何か案は?

4

2 に答える 2

3

次のように xpath を使用して、これらのノードにアクセスできます。

$doc = new DOMDocument;
$doc->loadHTML($html); // your content with a between '<html></html>' pair
$xpath = new DOMXpath($doc);
$elements = $xpath->query('//p[contains(comment(), "pagebreak")]/following-sibling::*|//p[contains(comment(), "pagebreak")]');
foreach ($elements as $elem) {
    $elem->parentNode->removeChild($elem);
}   

print $doc->saveHTML();

xpath の簡単な内訳:

  • // P 要素ごとに p.
  • //p[]配列のように、P のリストをフィルタリングします。
  • //p[contains(comment(), "pagebreak")]フィルターは、comment() 値に「改ページ」文字列が含まれている場合です。
  • //p[contains(comment(), "pagebreak")]/following-sibling::*後続の兄弟ごとに P を選択しました。
  • |もう一方の部分は、その部分を除いた同じパターンのユニオン ( ) だけfollowing-sibling::*です。

編集:

おそらく毛羽立ちの少ない xpath は次のようになります。

//p[contains(comment(), "改ページ")]/preceding-sibling::*[1]/following-sibling::*

これは、兄弟リストの1つを戻すことでトリックを実行し(その時点<p>で、コメントのあるものの前をターゲットにします)、そのノードのfollowing-siblings::*

于 2012-08-03T15:06:23.997 に答える
0

やったよ !私はそれを個人的な挑戦として取り、ついに正規表現でそれをやった!
このコードは最適化されていない可能性があります。改善方法を遠慮なく教えてください (ただし、DOM ではなく正規表現を使用します)。:)

$str = '<div>
    <h3>Test</h3>
    <img/>
    <p>Lorem ipsum</p>
    <p>dolor sit</p>
    <p><-- pagebreak --></p>
    <p>amet</p>
    <blockquote>
        <p>
            lol
        <p>
    </blockquote>
</div>';


$pagebreak_str = '-- pagebreak --';
$weird_replacement = '§~@';

$parsed = array();
$is_below_break = false;

while (preg_match ("#<([^/]+)>#isU",$str)) {
    if ($is_below_break) {
        $str = preg_replace ("#<" .$pagebreak_str. ">#isU", "", $str);
        $str = preg_replace ("#<[^/>]+>(.+)</[^/>]+>#isU", "", $str);
        $str = preg_replace ("#<[^/>]+/>#isU", "", $str);
    }
    else {
        $get = preg_replace ("#^(.*)<([^/>]+)>(.*)$#isU","$2",$str,1);

        if ($get == $pagebreak_str)
            $is_below_break = true;
        if (!$is_below_break)
            $str = preg_replace ("#<([^/>]+)>#isU","$weird_replacement$1>",$str,1);
        if (preg_match ("#</([^/>]+)>(.+)(<$pagebreak_str>)#isU", $str))
            $str = preg_replace ("#</([^/>]+)>#isU", "$weird_replacement/$1>", $str, 1);
    }
}
$str = preg_replace ("#$weird_replacement#isU", "<", $str);

echo $str;

このコードは、クロス タグ (<div><a></div></a>) などの html コーディング ミスがないことを前提としていますが、適切なコーディング スタイルで動作していることは間違いありません。
それを試してみてください!

于 2012-08-03T21:57:47.990 に答える