【发布时间】:2023-03-15 22:20:02
【问题描述】:
给定以下文本:
<p style="color: blue">Some text</p>
<p style="color:blue; margin-left: 10px">* Item 1</p> // Should match
<p style="margin-left: 10px">* Item 2</p>
<p style="margin-left: 20px">* Sub Item 1a</p> // Should match
<p style="margin-left: 20px">* Sub Item 2a</p>
<p style="margin-left: 10px">* Item 3</p>
<p style="margin-left: 20px">* Sub Item 1b</p> // Should match
<p style="margin-left: 20px">* Sub Item 2b</p>
<p style="margin-left: 30px">* Sub Item 1c</p> // Should match
<p>Some text</p>
<p style="color:blue; margin-left: 10px">* Item 1</p> // Should match
我正在尝试查找任何符合以下条件的 p 元素:
- 以星号字符开头
- 他们有一个
margin-left内联样式 - 前面的内容是:
-
p元素没有左边距 -
p元素的margin-left低于匹配的元素 - 任何其他元素
-
所以在示例中,我需要匹配以下元素:
<p style="color:blue; margin-left: 10px">* Item 1</p> (preceding element is a p but doesn't have any margin-left)
<p style="margin-left: 20px">* Sub Item 1a</p> (preceding element is a p but has a different margin-left value)
<p style="margin-left: 20px">* Sub Item 1b</p> (preceding element is a p but has a different margin-left value)
<p style="margin-left: 30px">* Sub Item 1c</p> (preceding element is a p but has a margin-left value lower than the current matched element)
<p style="color:blue; margin-left: 10px">* Item 1</p> (preceding element is a p but has no margin-left value)
我无法使用DomDocument,因为我收到的标记并不总是有效的标记(通常来自Microsoft Office > HTML 转换),所以我正在使用正则表达式来解决问题。
我目前的正则表达式是:
(?!<p style=".*?(margin-left:\s?(?!\k'margin')px;).*?">\* .*?<\/p>)<p style="(?P<styles>.*?)margin-left:\s?(?P<margin>[0-9]{1,3})px;?">\* (?P<listcontent>.*)<\/p>
但这仅基于现有的前面元素是 p 和 margin-left 匹配。
如何将匹配的margin-left 组考虑在内并返回大于前一个匹配的值?
我创建了一个online regex 来演示问题,其中包含示例数据和我当前的输出。
【问题讨论】:
-
这必须在单遍/方法中完成吗?你能匹配所有标签然后使用PHP减少集合吗?
-
因为它是更大的一系列操作的一部分,如果可能的话,它需要作为一个单一的正则表达式来完成。
-
我不相信这在一次通过中是可能的,因为您需要将值与其他值进行比较。您将能够找到包含
margin-left的p元素,但您需要一个辅助过程来进行比较。 -
如果没有办法将其作为一个正则表达式来解决,并且您有办法使用两遍来解决它,请将其写下来作为答案。
-
我会写一个答案,一个问题:最后一个元素如何匹配?它前面有一个没有边距的 p 元素,因此它未通过测试“除 p 元素之外的任何元素”?
标签: php regex pcre regex-negation regex-lookarounds