我正在尝试将旧版浏览器的<div
标记替换为HTML5元素。
我使用的代码如下。我简化了以便于理解:
<article class="article">article - Lorem ipsum dolor sit amet</article>
<pre>
<article class="article-pre">article - Lorem ipsum dolor sit amet</article>
<summary class="summary-pre">summary - Lorem ipsum dolor sit amet</summary>
</pre>
<code>
<article class="article-pre">Lorem ipsum dolor sit amet</article>
<summary class="summary-pre">Lorem ipsum dolor sit amet</summary>
</code>
我尝试做了一些实验,但都失败了。我使用的代码如下:
$dom = new DOMDocument;
$dom->loadHTML($content);
$xp = new DOMXPath($dom);
$nodes = $xp->query('//text()[not(ancestor::pre) and contains(.,' . $element . ')]');
foreach($nodes as $node) {
$node->nodeValue = str_replace($element, $replace, $node->nodeValue);
}
echo $dom->saveXML($dom->documentElement);
我希望这个东西适用于不支持HTML5元素的JavaScript禁用浏览器,因此不能使用任何JavaScript。
如果还有其他更好的方法可以使用php
,请建议。
答案 0 :(得分:1)
您可能过度简化了代码,因为它只会替换开始标记,这至少会导致浏览器跳入怪癖模式。
无论如何,这肯定是可以使用DOM(虽然它会因为不支持的HTML5元素而发出警告,请参阅https://stackoverflow.com/a/6090728/1392379),但是你的XPath查询是错误的,你不能简单地将数组传递给它。即使您的查询有效,它也只会选择所有单独的文本节点,因此不会有任何要替换的内容。
无法直接更改节点名称,您必须用新节点替换节点。这是一个使用静态XPath查询的示例。它将选定的节点属性和子节点复制到新的div
节点,然后用新的节点替换原始节点:
$dom = new DOMDocument;
$dom->loadHTML($content);
$xp = new DOMXPath($dom);
$nodes = $xp->query('//*[self::article|self::summary|self::aside][not(ancestor::pre) and not(ancestor::code)]');
foreach($nodes as $node)
{
$newNode = $dom->createElement('div');
while($node->childNodes->length)
{
$childNode = $node->childNodes->item(0);
$newNode->appendChild($dom->importNode($childNode, true));
}
while($node->attributes->length)
{
$attributeNode = $node->attributes->item(0);
$newNode->setAttributeNode($dom->importNode($attributeNode));
}
$node->parentNode->replaceChild($newNode, $node);
}
echo $dom->saveXML($dom->documentElement);
更新使用while
代替foreach
上的childNodes/attributes
修复了代码示例。后者将在不克隆要附加的节点时导致hickup,从而从正在迭代的节点列表中删除。
使用for
循环也应该可以正常工作:
for($i = 0; $i < $node->childNodes->length; $i ++)
{
$childNode = $node->childNodes->item($i);
$newNode->appendChild($dom->importNode($childNode, true));
}
for($i = 0; $i < $node->attributes->length; $i ++)
{
$attributeNode = $node->attributes->item($i);
$newNode->setAttributeNode($dom->importNode($attributeNode));
}
以及最初提到的克隆:
foreach($node->childNodes as $childNode)
{
$newNode->appendChild($dom->importNode($childNode->cloneNode(true), true));
}
foreach($node->attributes as $attributeNode)
{
$newNode->setAttributeNode($dom->importNode($attributeNode->cloneNode()));
}
$node->parentNode->replaceChild($newNode, $node);