使用PHP将标题标签降级(将h1转换为h2,将h2递归转换为h3)的字符串

4

我知道我们可以通过将字符串加载到

$doc = DOMDocument::loadXML($xml_str);

然后像这样获取H1标签:

$list = $doc->getElementsByTagName("h1");
for ($i = 0; $i < $list->length; $i++) {
   print($list->item($i)->nodeValue . "<br/>\n");
}

如果我想将这些H1标签改成H2标签,我有点迷茫。我已经了解了appendChild(),但那会让事情变得非常混乱。是否有一种方法可以递归地降低包含HTML的字符串中的标题标签?该方法将接受以下参数:

function demoteHeadings($xml_string, $top_level='H2'){
   //if string's highest heading is more than $top_level,
   //we demote all headings in this html by 1 level. i.e. if
   //h1 is found, all h1s, h2s and so on are demoted one level -
   //and we recursively    call this function again;
   if($top_level_in_xml > $top_level) demoteHeadings($output, $top_level);
}

我希望我的表述是有道理的。我的目标是自动解析客户在CMS中输入的标题... 他们在文章中使用H1,但实际上标题已经是一个H1了。有时候,还会有一个页面标题也是一个H1,这就真正地破坏了整个页面的结构。

4个回答

1
此解决方案将执行简单的搜索和替换,以降级标题标签。例如,它将更改<h1><h2><h2><h3>等等。
更强大的解决方案将使用DOMDocument,但我在Stack Overflow上找不到有效的解决方案。我决定不花时间用最精确或“正确”的方式解决此问题,因为这种解决方案在99%的情况下可能已足够好了。
for ($i = 1; $i <= 5; $i++) {
    $html = str_ireplace("<h" . $i, "<h" . $i . "_replace", $html);
    $html = str_ireplace("</h" . $i . ">", "</h" . $i . "_replace" . ">", $html);
}

for ($i = 1; $i <= 5; $i++) {
    $html = str_ireplace("<h" . $i . "_replace", "<h" . ($i + 1), $html);
    $html = str_ireplace("</h" . $i . "_replace" . ">", "</h" . ($i + 1) . ">", $html);
}

你可以通过改变迭代方向来避免第二个循环。for ($i = 5; $i >= 1; $i--)... - James K.

1

使用str_ireplace()不是更简单吗?

$content = str_ireplace(array('<h1>','</h1>'),array('<h2>','</h2>'),$input);

谢谢。有时候当你想得太多时,解决方案可能会太简单而难以想象。谢谢! - Vik
1
如果H标签具有类或其他属性,则此代码将无法正常工作。 - PolarTheDog
@PolarTheDog 很好的建议。不要使用正则表达式或简单的字符串操作来解析或修改HTML。使用DOMDocument - Lawrence Cherone

0

由于文章将在更深的容器中,适当地为它们设置样式不应该是一个问题。然而,我想你已经考虑过了。

我会因为建议使用正则表达式来解析HTML而受到指责...但是既然您的客户正在使用CMS输入HTML,我认为输入的语法非常可靠,元素没有属性,那么为什么不简单地使用str_replace呢?

啊,劳伦斯比我先说了这个。


1
是的,@lawrence-cherone已经做到了,但你同样受到赞赏。我感觉自己像个白痴。当然,str_replace会解决问题。谢谢。 - Vik

-1

另一种变体的 str_ireplace 解决方案,但更加健壮(考虑了 h1 到 h100)

function demoteHtmlHeaderTags($html)
{
        $originalHeaderTags = [];
        $demotedHeaderTags = [];

        foreach(range(100, 1) as $index)
        {
            $originalHeaderTags[] = '<h' . $index .'>';

            $originalHeaderTags[] = '</h' . $index . '>';

            $demotedHeaderTags[] = '<h' . ($index + 1) . '>';

            $demotedHeaderTags[] = '</h' . ($index + 1) . '>';
        }

        return str_ireplace($originalHeaderTags, $demotedHeaderTags, $html);
}

3
我很确定定义标题只有六级。 - Svish

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接