匹配标签内的标签
Match tags inside tag
我要修改:
<ins><br/> <b>bold</b> <br/><br/> <br/> <br/></ins> <br/> <ins> <br/> </ins>
至:
<ins><br/>NL: <b>bold</b> <br/>NL:<br/>NL: <br/>NL: <br/>NL:</ins> <br/> <ins> <br/>NL: </ins>
(在每个 <ins>
和 </ins>
标签内找到 <br/>
并将其更改为 <br/>NL:
。忽略 <ins>
之外的 <br/>
。此外, <ins>
可能包含各种其他标签)
要做到这一点,我有这个和平的代码:
$string= preg_replace('~(?:<ins>|(?!^)\G)(.*?)<br\/>~', '[=10=]NL:', $string);
https://regex101.com/r/xI8mW9/4
它会工作得很好,但问题是匹配不会在 </ins>
标签之后结束。如何仅使用 <ins>
和 </ins>
标签将 <br/>
替换为 <br/>NL:
。它在第一个 <ins>
之后修改每个 <br/>
我也试过模式:
~(<ins>.*?)(?<my_br><br/>)(?!NL:)(.*?</ins>)~
https://regex101.com/r/xI8mW9/15
(在这种情况下,每个 my_br 更改为 $1$2NL:$3) 问题:万一 <ins><br/></ins><br/><ins><br/></ins>
中间 <br/>
受到影响。
尝试按照评论中的建议使用 DOMDocument
进行操作:
$rendered_diff = "Some<ins>a<br/></ins><br/><ins>b<br/></ins>text";
$doc = new \DOMDocument();
$doc->loadHTML($rendered_diff);
$items = $doc->getElementsByTagName('ins');
for ($i = 0; $i < $items->length; $i++) {
foreach ($items->item($i)->childNodes as $node) {
if ($node->nodeName == 'br') {
$node->appendData('NL:');
}
}
}
$doc->saveHTML();
dd($rendered_diff);
出现错误:
ERROR: Call to undefined method DOMElement::appendData()
不知道为什么这种方法不好。
您可以试试下面的代码:
<?php
$rendered_diff = "<br/>Some<ins>a<br/><div>blablaa</div></ins><br/><ins>b<br/></ins>text";
$doc = new \DOMDocument();
$doc->loadHTML($rendered_diff);
$xpath = new DOMXpath($doc);
$items = $doc->getElementsByTagName('ins');
foreach ($xpath->query("//ins/br") as $br) {
$text = $doc->createTextNode('NS:');
$br->parentNode->insertBefore( $text, $br->nextSibling);
}
echo $doc->saveXML();
输出如下:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><br/>Some<ins>a<br/>NS:<div>blablaa</div></ins><br/><ins>b<br/>NS:</ins>text</body></html>
这似乎解决了问题。
请注意,我稍微修改了您的初始 XML,以测试您的
Ignore <br/>
outside <ins>
状况。见第一条<br/>
。
回答您的问题
Have no idea why this approach is bad.
你的方法不好,因为this,把它和我放在上面的代码比较一下:后者看起来不是更干净吗?此外,它使用 XPath,您可以创建更复杂的查询来匹配某些元素,而不仅仅是 <ins>
中的 <br>
我要修改:
<ins><br/> <b>bold</b> <br/><br/> <br/> <br/></ins> <br/> <ins> <br/> </ins>
至:
<ins><br/>NL: <b>bold</b> <br/>NL:<br/>NL: <br/>NL: <br/>NL:</ins> <br/> <ins> <br/>NL: </ins>
(在每个 <ins>
和 </ins>
标签内找到 <br/>
并将其更改为 <br/>NL:
。忽略 <ins>
之外的 <br/>
。此外, <ins>
可能包含各种其他标签)
要做到这一点,我有这个和平的代码:
$string= preg_replace('~(?:<ins>|(?!^)\G)(.*?)<br\/>~', '[=10=]NL:', $string);
https://regex101.com/r/xI8mW9/4
它会工作得很好,但问题是匹配不会在 </ins>
标签之后结束。如何仅使用 <ins>
和 </ins>
标签将 <br/>
替换为 <br/>NL:
。它在第一个 <ins>
<br/>
我也试过模式:
~(<ins>.*?)(?<my_br><br/>)(?!NL:)(.*?</ins>)~
https://regex101.com/r/xI8mW9/15
(在这种情况下,每个 my_br 更改为 $1$2NL:$3) 问题:万一 <ins><br/></ins><br/><ins><br/></ins>
中间 <br/>
受到影响。
尝试按照评论中的建议使用 DOMDocument
进行操作:
$rendered_diff = "Some<ins>a<br/></ins><br/><ins>b<br/></ins>text";
$doc = new \DOMDocument();
$doc->loadHTML($rendered_diff);
$items = $doc->getElementsByTagName('ins');
for ($i = 0; $i < $items->length; $i++) {
foreach ($items->item($i)->childNodes as $node) {
if ($node->nodeName == 'br') {
$node->appendData('NL:');
}
}
}
$doc->saveHTML();
dd($rendered_diff);
出现错误:
ERROR: Call to undefined method DOMElement::appendData()
不知道为什么这种方法不好。
您可以试试下面的代码:
<?php
$rendered_diff = "<br/>Some<ins>a<br/><div>blablaa</div></ins><br/><ins>b<br/></ins>text";
$doc = new \DOMDocument();
$doc->loadHTML($rendered_diff);
$xpath = new DOMXpath($doc);
$items = $doc->getElementsByTagName('ins');
foreach ($xpath->query("//ins/br") as $br) {
$text = $doc->createTextNode('NS:');
$br->parentNode->insertBefore( $text, $br->nextSibling);
}
echo $doc->saveXML();
输出如下:
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><br/>Some<ins>a<br/>NS:<div>blablaa</div></ins><br/><ins>b<br/>NS:</ins>text</body></html>
这似乎解决了问题。
请注意,我稍微修改了您的初始 XML,以测试您的
Ignore
<br/>
outside<ins>
状况。见第一条<br/>
。
回答您的问题
Have no idea why this approach is bad.
你的方法不好,因为this,把它和我放在上面的代码比较一下:后者看起来不是更干净吗?此外,它使用 XPath,您可以创建更复杂的查询来匹配某些元素,而不仅仅是 <ins>
<br>