使用多个正则表达式捕获匹配的嵌套xml标记

时间:2014-06-27 08:20:47

标签: xml regex

假设我有一个xml文件,其中包含嵌套在自身内的标记,例如

<TAG>one<TAG>two</TAG>one</TAG>

this page开始,我有两个正则表达式的例子没有正确匹配这个字符串,例如你会得到

<TAG>one<TAG>two</TAG>

不平衡。根据谷歌的说法,找不到能够正确解析HTML的正则表达式,例如herehere

  

使用正则表达式无法进行整个HTML解析,因为它取决于匹配开头和结束标记,这是正则表达式无法实现的。

     

正则表达式只能匹配常规语言,但HTML是无上下文的语言。你可以用HTML上的regexp做的唯一的事情就是启发式,但这并不适用于所有条件。应该可以呈现一个HTML文件,它将被任何正则表达式错误地匹配。

这是一个很好的明确的理论答案,但它让我思考:是否有可能以编程方式,使用多个正则表达式和/或循环?

2 个答案:

答案 0 :(得分:3)

正则表达式不规律。许多主要的正则表达式都允许您匹配各种递归结构。

因此,为了匹配您在PCRE中的示例,您可以编写(demo):

<TAG>(?:[^<>]+|(?R))*</TAG>

无需任何其他代码或正则表达式。那不是XML解析器。

答案 1 :(得分:1)

这是一个简单的递归下降xml解析器,我现在正在编写它,因为它有点粗糙和准备好,用红宝石写它,因为你没有指定语言。 不要在生产中使用它(或任何地方,这只是为了好奇心):

string = "<TAG>one<OTHER_TAG>two</OTHER_TAG>one</TAG>"
regex_xml_parser = -> string {
  stuff_before = []
  matches = []
  stuff_after = []
  while string =~ />/
    stuff_before << string[ /^[^<]*/ ]
    string.sub!(/^[^<]*/, '')
    matches << string.match(/<([^>]+)>(.*)<\/\1>/)
    string.sub!(/<([^>]+)>(.*)<\/\1>/, '')
    stuff_after << string[ /[^>]*$/ ]
    string.sub!(/[^>]*$/, '')
    p [ stuff_after, "stuff_after" ]
  end
  values = stuff_before + stuff_after + [string]
  return_value = values.clone
  matching_nodes = matches.map { |match| make_matches[match]}
  {values: return_value.select { |x| x != "" },
  nodes: matching_nodes}
}

make_matches = -> match_item {
  {match_item[1] => regex_xml_parser[match_item[2]]}
}

regex_xml_parser[string]

请记住,我们实际上是在构建一个解析器,所以我认为使用已经存在的解析器更容易一些。