我正在尝试使用正则表达式来查找不完整的没有属性的 xml 标记。到目前为止,我已经设法想出了这个正则表达式</?\s*([a-zA-Z0-9]?:\s+)?[a-zA-Z0-9]*(?!>)
,但这并不能解决问题。在这样的 xml 中:
<abc>
</abc>
<ab>
</ab
<s:ab
我想匹配</ab
和<s:ab
(因为它们最后都缺少“>”)。有没有办法在 c# 中使用正则表达式来做到这一点?
你很接近。您的主要问题是,当负前瞻失败时,模式会回溯。您可以通过将前瞻之前的部分放在非回溯原子组中来避免这种情况:(?>no backtracking in here)
.
例如:
(?xi) # turn on eXtended (ignore spaces/comments) and case-Insensitive mode
(?> # don't backtrack
< /? # tag start (no space allowed after it)
[a-z0-9]+ # tag name/space
(?: : [a-z0-9]+ )?
\s* # optional spaces
)
(?! > ) # no ending
请注意,这将<foo
在<foo bar>
.
正如人们所说,这可能是徒劳的——因为 XML 不是一种常规语言。但是,您的部分问题是您的前瞻性。你只需要确保它后面没有紧跟一个右尖括号——这意味着即使你不想要它们,类似<ab
of 的东西也会匹配。<abc>
所以你需要在你的前瞻中包含整个标签结构。
为了匹配您提供的确切数据,我可以使用正则表达式:
#</?([a-z]?:)?[a-z]*(?!/?([a-z]?:)?[a-z]*>)#
您可以在此处查看实际操作。这里的关键是确保正则表达式引擎在任何时候都不能回溯(例如,删除一个字符)以验证前瞻。还有其他方法可以做到这一点 - 例如所有格量词,它拒绝在正常回溯过程中放弃其匹配的标记,但标准 .NET 引擎不支持所有格匹配。它确实支持原子组 - 其行为方式相同,但使用组而不是量词。您可以在这里看到,我已将标签的整个开口包裹在一个原子组中。( (?> ... )
)
#(?></?([a-z]?:)?[a-z]*)(?!>)#
您可以自由输入自己的正则表达式来确定标签的格式,但我必须说这个正则表达式已经在推动代码可读性的极限,而使用合法的 xml 标签名称将进一步推动它在那个方向。尽管如此,我希望这有助于阐明这个错误。
如果您只是想在单个 xml 文件中查找错误,请尝试在 Google Chrome 网络浏览器中打开它 - 它会显示错误所在的行。
但是,如果您有很多文件必须在代码中处理,那么您需要比正则表达式更强大的东西。