【问题标题】:Regex Issue w/ Single Line XML带单行 XML 的正则表达式问题
【发布时间】:2013-01-28 11:53:31
【问题描述】:

我正在通过 XML 创建一个 word 文档,该过程的最后一步是删除所有空白行。当 xml 是多行时,我似乎有一个有效的模式;但是,它是作为单行生成的,这打破了我的 preg_replace。考虑以下 XML:

**<w:p** w:rsidR="009E48E3" w:rsidRPr="008C0DAB" w:rsidRDefault="009E48E3" w:rsidP="004E0AE3"><w:pPr><w:ind w:right="-540"/></w:pPr><w:r w:rsidRPr="008C0DAB">**<w:t>text that should be included</w:t>**</w:r>**</w:p><w:p** w:rsidR="009E48E3" w:rsidRPr="008C0DAB" w:rsidRDefault="009E48E3" w:rsidP="004E0AE3"><w:pPr><w:numPr><w:ilvl w:val="1"/> <w:numId w:val="10"/></w:numPr><w:tabs><w:tab w:val="clear" w:pos="1440"/><w:tab w:val="num" w:pos="1080"/></w:tabs><w:ind w:right="-540" w:hanging="720"/><w:rPr><w:noProof/></w:rPr></w:pPr><w:r><w:rPr><w:noProof/></w:rPr><w:lastRenderedPageBreak/>**<w:t> ; </w:t>**</w:r>**</w:p>**

插入星号只是为了提高可读性

空白行始终位于<w:t></w:t> 标记之间,并包含句点或分号。因此,第一个<w:p> 标记应保留,而第二个应删除。

这是我的模式:<w:p .*<w:t>[ ]+?(\.|;)[ ]+?<\/w:t>.*?<\/w:p>

感谢您的帮助,谢谢!

【问题讨论】:

  • 我认为您在第一个 .* 之后错过了 ?
  • 不幸的是我也试过了,没有运气。我很确定我需要让它完全不贪婪,不知道我错过了什么
  • 使第一个 .* 变得懒惰是行不通的,因为如果第一个 <w:t> 元素不是空行,.*? 将使用该元素和 XML 的其余部分,直到下一个<w:t> 元素。这将一直持续到遇到空行 <w:t> 元素。然后,该模式的其余部分将成功捕获该元素以及该元素的父 <w:p> 标记的其余部分。结果是当空白行元素被捕获时,所有前面的连续非空白元素也被包含在捕获中。

标签: php regex


【解决方案1】:

您的模式的问题在于,第一个 .* 将直接读取到 XML 的末尾,然后最终回溯到 last <w:t> 标记之前。从那里,模式的其余部分将成功匹配 XML 的其余部分。结果 - 整个 XML 被捕获!

Itchy 模式的问题在于前瞻(?!.*w:p ) 表示“只有在前面没有更多<w:p> 标记时”。换句话说,该模式将只匹配 last <w:p> 元素(如果需要删除它)。

所有这些问题都源于.*的使用。我的两部分座右铭是,除非绝对必要,否则尽量不要使用它。那么,如果你发现它绝对需要使用它,尽量不要使用它 :)

以下模式将起作用:

<w:p [^<]++(?:(?!<w:t>)<[^<]++)++<w:t> *+[\.;] *+<\/w:t>[^<]*+(?:(?!<\/w:p>)<[^<]++)++<\/w:p>

注意事项:

  1. .* 根本没有使用!
  2. 所有格量词 ++*+ 并不是真正需要的,但会加快正则表达式的速度。
  3. 如果元素总是这样结束,最后一部分可以简化为<\/w:t><\/w:r><\/w:p>

【讨论】:

  • 像个魅力罗宾一样工作,谢谢!这消耗了我整个星期六和整个周末的大脑,谢谢你让我摆脱了痛苦:)
【解决方案2】:

对于这个字符串,您提供了以下模式:

<w:p (?!.*w:p ).*?<w:t>[ ]+?(\.|;)[ ]+?<\/w:t>.*?<\/w:p>

我已经在 Rubular 上测试过了。

它使用negative lookahead

【讨论】:

  • 感谢 Itchy,这似乎是朝着正确方向迈出的一步;但是,当我将它放入我的应用程序时,我仍然遇到问题。如果您在 Rubular 上转到 this example,您会再次看到它找不到匹配项,但如果您将最后一个 &lt;w:p&gt; 放在新行上,它会找到 1 个匹配项,我仍然不确定为什么。
  • 我认为您也可以使用负前瞻来修复它。请查看我提供的链接。否则,您可以将文档拆分为 &lt;w:p 的片段,然后删除空的片段并重新加入。
猜你喜欢
  • 2016-01-06
  • 1970-01-01
  • 2011-05-13
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多