首页 > 解决方案 > 在下一个中插入一个 id 属性

在 PHP 中的字符串中标记

问题描述

我在一个名为 $body 的变量中有一个字符串

$body = '<p>Text.</p>
        <div class="my-class">Text.</div>
        <p>Text.</p>
        <p>Text.</p>
        <p>Text.</p>';

我想把它改成

$body = '<p>Text.</p>
            <div class="my-class">Text.</div>
            <p id="p1">Text.</p>
            <p>Text.</p>
            <p>Text.</p>';

假设<p>Text.</p>前面<div class="my-class">有未知数量的段落,后面有未知数量的<p>Text.</p>段落。所以我不知道<div class="my-class">字符串变量中的位置。

我如何在 PHP 中做到这一点?

这是我想出的最好的。

稍后在脚本中,我使用 explode() 将 $body 字符串转换为 $body 数组

$html_tags = [
  '</p>' => '</p>|',
  '</div>' => '</div>|',
  '\/>' => '\/>|',
];
foreach ($html_tags as $key => $value) {
  $body = str_replace($key, $value, $body);
}
$paragraphs = explode('|', $body);

// Remove trailing </p>.
array_pop($paragraphs);

我可以这样做,因为我知道 $body 包含的所有标签。

现在 $body 是一个数组,我可以添加' id="p1"'到 p 标签<div class="my-class">之后

foreach ($body as $key => $value) {
  if (strpos($value, 'my-class') !== FALSE) {
    $next_paragraph = $array[$key - 1];
    $newText = ' id="p1"';
    $newstr = substr_replace($next_paragraph, $newText, 6, 0);
    dsm($newstr);
  }
}

但那时我正处于一个遍历数组的索引上。一个数组索引似乎无法更改下一个数组索引。

但在它是一个数组之前,它是一个字符串。如果我可以改变字符串,我会很高兴。

标签: phphtml

解决方案


这不是使用 HTML 的方式。它是一种标记语言,需要这样解析。使用 XPath 查找您要查找的元素,并使用 DomDocument 更改它。

<?php
$body = '<p>Text.</p>
        <div class="my-class">Text.</div>
        <p>Text.</p>
        <p>Text.</p>
        <p>Text.</p>';

$dom = new DomDocument;
$dom->loadHTML("<html>$body</html>", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DomXPath($dom);
// this looks complicated, but essentially things inside square brackets are conditions
// so we're looking for the first p with a preceding div that has a class of "my-class"
// note XPath is not zero-based, hence the [1] instead of [0]
$paras = $xpath->query("//p[preceding::div[@class='my-class']][1]");
// alter the element; the nodes are all references so $dom is also getting updated
// a list is always returned even with one element, so have to use array notation
$paras[0]->setAttribute("id", "p1");

// output the new HTML
$html = "";
foreach ($dom->documentElement->childNodes as $n) {
    $html .= $dom->saveHTML($n);
}
echo $html;

输出:

<p>Text.</p>
        <div class="my-class">Text.</div>
        <p id="p1">Text.</p>
        <p>Text.</p>
        <p>Text.</p>

推荐阅读