嵌套XML属性的正则表达式

时间:2016-05-09 10:24:58

标签: regex recursive-regex

假设我有以下字符串:

"<aa v={<dd>sop</dd>} z={ <bb y={ <cc x={st}>ABC</cc> }></bb> }></aa>"

如何编写通用正则表达式(标记名称更改,属性名称更改)以匹配{}内的内容<dd>sop</dd><bb y={ <cc x={st}>ABC</cc> }></bb>

正则表达式我写了"(\s*\w*=\s*\{)\s*(<.*>)\s*(\})"匹配

"<dd>sop</dd>} z={ <bb y={ <cc x={st}>ABC</cc> }></bb>"这是不正确的。

2 个答案:

答案 0 :(得分:2)

在通用正则表达式中,没有办法以良好的方式处理嵌套。因此,当出现这样的问题时所有的胜利 - 永远不要使用正则表达式来解析XML / HTML。

在一些简单的情况下,它可能是有利的。如果像在你的例子中那样,嵌套级别有限,你可以简单地为每个级别添加一个正则表达式。

现在让我们分步进行。要处理第一个非嵌套属性,您可以使用

{[^}]*}

这匹配一个起始大括号,后跟任意数量的一个右大括号,最后是一个右大括号。为简单起见,我会把它的核心放在一个非捕获组中,比如

{(?:[^}])*}

这是因为在插入备用的时候,需要它。

如果您现在允许除了右括号[^}])以外的任何其他嵌套级别的大括号​​,只需加入第一个正则表达式,像

{(?:{[^}]*}|[^}])*}
    ^^^^^^^    original regex inserted as alternative (to it self)

它允许一个级别的嵌套。再次这样做,加入这个正则表达式作为自己的替代,比如

{(?:{(?:{[^}]*}|[^}])*}|{[^}]*}|[^}])*}
        ^^^^^^^^^^^^^^^    previous level repeated

将允许另一级别的嵌套。如果需要,可以重复更多级别。

这不能处理属性名称和东西的捕获,因为你的问题不是很清楚你想要什么,但它向你展示了一种方式(最容易理解,或者......:P )处理正则表达式中的嵌套。

You can see it handle your example here at regex101

此致

答案 1 :(得分:0)

你正试图处理平衡的大括号。这需要递归正则表达式。根据定义,递归正则表达式不是常规的。无论如何,一些语言支持它们,例如Perl,PHP,ruby。 This是关于该主题的好教程。

通常,您应该使用完全成熟的解析器(如yacc)提取此类信息。

这是一个可以处理非平衡大括号的正则表达式:([ =]*)=(\{[^}]*\})。这将匹配{<dd>sop</dd>}{st},这是正确的。不幸的是,它也会匹配{ <bb y={ <cc x={st},这不是你想要的。