注意正则表达式和 XML 解析
使用正则表达式捕获 XML 中的数据总是有点危险。通常,这些<NODE2>
标签可以是书面的< node2 >
,或者<NODE2 id="3425">
是有效的 XML。具有正向前瞻和后向的正则表达式将不起作用,因为它们通常必须是固定长度。
如果您的 XML 可以安全更改,那么您可以使用它:
/(?<=NODE2>)\s*(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s*(?=<\/NODE2)/gi
你可以在这里测试它:https ://regex101.com/r/Bsul9m/2
我添加了i
不区分大小写的标志,以防 XML 包含<node2>
而不是<NODE2>
.
你想捕捉单词,所以我使用了这个\w+
模式。但这不包括特殊字符。因此,您可以将其替换为其他内容,例如\p{L}
匹配任何语言的任何字母,并使用\d
or添加数字[0-9]
。
这是为了以最少的更改来回答您的问题。
现在,一个更好的正则表达式可以在不使用解析器的情况下处理 XML
这一次,我不会使用您的前瞻和后视模式,因为我们捕获更多并不重要,因为无论如何我们都会捕获您的 4 个项目。
我们希望能够匹配这些标签:
- 不区分大小写:
<node2>
,<Node2>
或<NODE2>
.
- 可选空格:
< NODE2>
, < node2 >...< / node2>
.
- 可选属性:
<node2 attribute="value" id="something">
.
- 可选命名空间:
<my-namespace:node2 id="123">
这导致正则表达式更加灵活:
/<\s*((?:[\w-]+:)?)node2\b[^>]*>\s*(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s*<\s*\/\s*\1node2\s*>/gi
你可以在这里测试它:https ://regex101.com/r/j6Bcbs/1
这个的优点是它在 XML 结构上会更灵活一些。它适用于以下内容:
<NODE1>A1</NODE1>
<NODE2 id="1234" title="Second node">B1 B2 B3 B4 </ NODE2 >
< node2>A1 B2 C3 ZZZ4</node2>
<namespace:node2>A1 A2 A3 A4</namespace:node2>
< other-namespace:node2 attr = "value"> W X Y Z</other-namespace:node2>
<NODE3>C1</NODE3>
您将在捕获的组 2 到 5 中拥有 4 个项目。这是因为命名空间是在第一个组中捕获的,因为它在结束标记中必须相同。
解释:
<\s*
匹配开始标签和可选空格。
((?:[\w-]+:)?)
是第一个获得可选命名空间的捕获组(它不是 100% 有效,但在大多数情况下都可以使用)。所以这将捕获namespace:
或other-namespace:
在上面的示例中。
node2\b[^>]*>
将node2匹配一个单词结尾,然后是零个或多个不是结束标记的字符,然后是结束标记。
\s*(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s*
是您想要获取的 4 个项目的 4 个捕获组(索引 2 到 5)。它们可以被空格包围,并且必须用空格分隔。
<\s*\/\s*\1node2\s*>
是带有对捕获组 1 的反向引用的结束标记,该捕获组是可选的命名空间。