正则表达式以查找可能为空的命名XML标记

时间:2019-03-25 13:22:27

标签: regex

我在查找文本块内的特定命名xml标签时遇到问题,该文本块可能为空也可能不是空。我不确定问题是否可以通过正则表达式解决。

例如,我有以下文本块:

...<item name="xxx">yyyy</item>....

要使用属性过滤掉'item'标签,请使用以下正则表达式:

<item(.*?)>(.*?)</item>|<item(.*?)./>

此正则表达式还可以与空标签一起使用,例如以下示例文本:

...<item name="zzz" />....

我的问题是我的文本包含多个'item'标签。只要我不像下面的示例文本块中那样将空标记与非空标记混合在一起,就可以使用此功能

...<item name="zzz" />....
...<item name="xxx">yyyy</item>....

我使用的正则表达式不适用于这种称呼,因为它找到了第一个结果:

<item name="zzz" />.......<item name="xxx">yyyy</item>

我的问题是:使用正则表达式可以解决此问题吗? 我的第一个想法就是使用“ AND NOT”之类的组合

(<item(.*?))(?!/>)>(.*?)</item>

但是我在这个问题上失败了。

将正则表达式应用于给定文本块的Java代码如下:

Pattern pattern = Pattern.compile("<item(.*?)>(.*?)</item>|<item(.*?)./>", Pattern.DOTALL);
Matcher matcher = pattern.matcher(textblock);
while (matcher.find()) {
   String attributes = matcher.group(1);
   ....
}

1 个答案:

答案 0 :(得分:1)

如果使用w3c定义的标签属性regex,则您的正则表达式将起作用。
您可以100%准确地找到开放的独立标签。

但是,您需要一个使用原子组的引擎,您也可以区分
在开放和自我包含之间,如下所示:

原始:

(?s)(?:(<item(?>\b(?:".*?"|'.*?'|[^>]*?)*>)(?<=/>))|(<item(?>\b(?:".*?"|'.*?'|[^>]*?)*>)(?<!/>))(.*?)(</item\s*>))

双引号:

"(?s)(?:(<item(?>\\b(?:\".*?\"|'.*?'|[^>]*?)*>)(?<=/>))|(<item(?>\\b(?:\".*?\"|'.*?'|[^>]*?)*>)(?<!/>))(.*?)(</item\\s*>))"

https://regex101.com/r/R3iVVW/1

 (?s)
 (?:
      (                                    # (1 start), Self Contained item
           <item
           (?>                                  # Atomic to trap self contained
                \b  
                (?: " .*? " | ' .*? ' | [^>]*? )*
                > 
           )
           (?<= /> )                            # Must be a self contained item

      )                                    # (1 end)

   |                                     # OR, 

      (                                    # (2 start), Open item
           <item
           (?>                                  # Atomic to trap self contained
                \b 
                (?: " .*? " | ' .*? ' | [^>]*? )*
                >
           )
           (?<! /> )                            # Not a self contained item
      )                                    # (2 end)
      ( .*? )                              # (3), Item content
      ( </item \s* > )                     # (4), Close item
 )

标为:

Regex1:   (?s)(?:(<item(?>\b(?:".*?"|'.*?'|[^>]*?)*>)(?<=/>))|(<item(?>\b(?:".*?"|'.*?'|[^>]*?)*>)(?<!/>))(.*?)(</item\s*>))
Options:  < none >
Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   14
Elapsed Time:    4.73 s,   4728.21 ms,   4728214 µs
Matches per sec:   148,047