0

试图找到这个问题的正则表达式:

PHP解析xml文件错误

尝试在以下字符串中匹配“137b”,使用否定的前瞻和后瞻断言:

<Rate Symbol="EURTRY">
    <Bid>2.29443</Bid>
    <Ask>2.29562</Ask>
    <High>2.29841</High>
    <Low>2.28999</Low>

 137b

 <Direction>1</Direction>
    <Last>23:29:11</Last>
</Rate>

谁能指出为什么这个正则表达式不起作用:

(?<!(<\w+>))[a-zA-Z0-9_\.:]+(?!(</\w+>))

意图:包含 "a-zA-Z0-9_.:" 的字符串前后没有 XML 标记,因此它应该匹配 "137b" ,但事实并非如此。

这是正则表达式的链接: http ://regexr.com?32rk4

而没有否定断言的相同正则表达式(<\w+>)[a-zA-Z0-9_\.:]+(</\w+>)正确匹配 xml 标签内的所有字符串。

http://regexr.com?32rk7

4

2 回答 2

2

大多数 regex 风格不支持可变长度的lookbehind。这里看起来就是这种情况。试试这个,以匹配所有文本后跟一个开始标签而不是结束标签:

[a-zA-Z0-9_\.:]+(?=\s*<)(?!(</\w+>))

不用说,解析 XML 的正则表达式方法很脆弱,这也不例外。

于 2012-11-19T06:00:07.523 回答
0

PHP 不会让您为此使用lookbehind,但lookbehind 无论如何都不是这项工作的最佳工具。(几乎从来没有。)您应该能够通过前瞻来解决问题。如果您可以对文档结构做出某些假设,这将容易得多。例如,您能否确定封闭节点始终命名为Rate,并且其子节点永远不会有自己的子节点(属性或元素)?换句话说,你永远不会看到这样的东西:

<Rate Symbol="EURUSD">
    <Bid>1.27554</Bid>
        <foo>bar</foo>
    <Ask foo="bar">1.27578</Ask>
</Rate>

如果是这样,您可以使用正向前瞻来匹配任意数量的完整子节点,后跟结束</Rate>标记:

[a-zA-Z0-9_.:]++(?=\s*(?><(\w+)>[^<]*</\1>\s*)*+</Rate>)

解释:

[a-zA-Z0-9_.:]++
(?=
  \s*
  (?>
    <(\w+)>       # match an opening tag and capture its name
    [^<]*         # consume the content
    </\1>         # match the closing tag
    \s*
  )*+           # do this zero or more times
  </Rate>       # confirm we're inside a <Rate> element
)

这甚至可以扩展到处理您在原始问题中提到的其他垃圾,但是正则表达式变得如此丑陋,我认为这不值得。

于 2012-11-19T10:14:16.140 回答