【问题标题】:Regex to find a string not inside xml tags?正则表达式查找不在 xml 标签内的字符串?
【发布时间】:2012-11-19 05:48:45
【问题描述】:

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

PHP parsing xml file error

尝试匹配以下字符串中的“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

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

http://regexr.com?32rk7

【问题讨论】:

    标签: php xml regex


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      如果是这样,您可以使用 positive 前瞻来匹配任意数量的完整子节点,后跟 &lt;/Rate&gt; 结束标记:

      [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
      )
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-03
        • 2017-05-15
        • 2013-05-21
        • 1970-01-01
        相关资源
        最近更新 更多