假设我有一个xml文件,其中包含嵌套在自身内的标记,例如
<TAG>one<TAG>two</TAG>one</TAG>
从this page开始,我有两个正则表达式的例子没有正确匹配这个字符串,例如你会得到
<TAG>one<TAG>two</TAG>
不平衡。根据谷歌的说法,找不到能够正确解析HTML的正则表达式,例如here或here。
使用正则表达式无法进行整个HTML解析,因为它取决于匹配开头和结束标记,这是正则表达式无法实现的。
正则表达式只能匹配常规语言,但HTML是无上下文的语言。你可以用HTML上的regexp做的唯一的事情就是启发式,但这并不适用于所有条件。应该可以呈现一个HTML文件,它将被任何正则表达式错误地匹配。
这是一个很好的明确的理论答案,但它让我思考:是否有可能以编程方式,使用多个正则表达式和/或循环?
答案 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]
请记住,我们实际上是在构建一个解析器,所以我认为使用已经存在的解析器更容易一些。