2017-05-04 1 views
1

皆さん、私は、HTML文字列を解析し、任意のpタグの周りCDATAタグを追加しようとしているので、<p>something</p><p><!CDATA[<p>blah</p>]]</p>になってしまうでしょう。これは私がその点に欲しいものを行います。のDOMDocumentとUL tages

$html_str = '<p><strong>blah blah blah</strong></p><ul><li>blah blah blah</li><li>blah blah blah</li><li>blah blah blah</li></ul><p>blah blah blah</p>';  
$domdoc = new DOMDocument();          
$domdoc->loadHTML($html_str); 

foreach($domdoc->getElementsByTagName("p") as $pnode) { 
    $cdata = $domdoc->createCDATASection('<p>'. $pnode->nodeValue .'</p>'); 
    $pnode->replaceChild($cdata, $pnode->childNodes->item(0)); 
} 
echo $domdoc->saveXML(); 

問題があっpタグ内にない文字列の一部ulタグがあると私はそれらと同じことを行う必要があります。それらは、<p><!CDATA[<ul>blah</ul>]]</p>のように、pタグ内にCDATAで囲む必要があります。

私はちょうど最初の文字列を通過し、任意の ulの前に pタグを追加してから、ちょうどのために、 CDATA内にあるように、すべての pのタグを取得するために、第2パスで上記と同じを使用することができることを期待していた

例:明らかに

$html_str = '<p><strong>blah blah blah</strong></p><ul><li>blah blah blah</li><li>blah blah blah</li><li>blah blah blah</li></ul><p>blah blah blah</p>';  
$domdoc = new DOMDocument();          
$domdoc->loadHTML($html_str); 

foreach($domdoc->getElementsByTagName("ul") as $ulnode) { 
    $cdata = $domdoc->createElement("p",$ulnode->nodeValue); 
    $domdoc->replaceChild($cdata,$ulnode); 
} 

foreach($domdoc->getElementsByTagName("p") as $pnode) { 
    $cdata = $domdoc->createCDATASection('<p>'. $pnode->nodeValue .'</p>'); 
    $pnode->replaceChild($cdata, $pnode->childNodes->item(0)); 
} 
echo $domdoc->saveXML(); 

、これは動作しませんでした、私はli項目の内容だけになってしまいました。私はそのような2つのパスを行うことはできませんか?それとも、ulは子供や何かを持つ親ですか?

は私がで終わるしようとしていることはこれです:

<p><!CDATA[<p><strong>blah blah blah</strong></p>]]></p> 
<p><!CDATA[<ul><li>blah blah blah</li><li>blah blah blah</li><li>blah blah blah</li></ul>]]></p> 
<p><!CDATA[<p>blah blah blah</p>]]></p> 
+0

私はCDATAタグにあまり慣れていませんが、あなたには閉じ括弧があまりにも多い( ']')ように見えます。 – freginold

+0

'p'の中に 'ul'タグがいくつかあるかもしれませんか? – revo

答えて

0

まず第一に、すべては、あなたが<![CDATA[]]>は、有効なHTMLの構成要素ではないとして、HTMLとXMLの概念をミックスしようとしています。だから、私はすべてをXMLとして扱うのが最善だと思う。ただし、これは、HTMLフラグメントが有効なXMLである必要があります。

次に、HTMLフラグメントにルート要素がないため、(DOMDocument::createDocumentFragment経由)を使用してルートレスフラグメントをインポートします。

次に、既存の<p>要素を最初にループします。それ以外の場合は、追加した<p>要素をループします。その後、既存の<ul>要素をループします。

お気づきのように、DOMElement->nodeValuewill merely give you the textContent of a nodeしたがって、代わりにDOMDocument::saveXML(DOMNode $node)を使用してXML文字列をCDATAセクションに挿入します。

最後に、新しく作成された<p>要素にCDATAセクションをラップします。それがすべてを包むために

、これはあなたの所望の出力を取得する方法である:

$html_str = '<p><strong>blah blah blah</strong></p><ul><li>blah blah blah</li><li>blah blah blah</li><li>blah blah blah</li></ul><p>blah blah blah</p>'; 

$domdoc = new DOMDocument(); 

$domfrag = $domdoc->createDocumentFragment(); 
$domfrag->appendXML($html_str); 

$domdoc->appendChild($domfrag); 

foreach($domdoc->getElementsByTagName("p") as $pnode) { 
    $cdata = $domdoc->createCDATASection($domdoc->saveXML($pnode)); 
    $newPnode = $domdoc->createElement("p"); 
    $newPnode->appendChild($cdata); 
    $pnode->parentNode->replaceChild($newPnode, $pnode); 
} 

foreach($domdoc->getElementsByTagName("ul") as $ulnode) { 
    $cdata = $domdoc->createCDATASection($domdoc->saveXML($ulnode)); 
    $newPnode = $domdoc->createElement("p"); 
    $newPnode->appendChild($cdata); 
    $ulnode->parentNode->replaceChild($newPnode, $ulnode); 
} 

/** 
* unfortunately, LIBXML_NOXMLDECL is not supported 
* so $domdoc->saveXML(null, LIBXML_NOXMLDECL) does not work 
* @see https://bugs.php.net/bug.php?id=50989 
*/ 
echo $domdoc->saveXML(); 

/** 
* so, to drop the <?xml declaration line, you could do the following: 
*/ 
foreach($domdoc->childNodes as $node) { 
    echo $domdoc->saveXML($node) . PHP_EOL; // PHP_EOL is optional 
} 

あなたはview this example onlineをすることができます。