使用与序列匹配两次的正则表达式从xml中删除空元素

时间:2016-01-20 13:19:09

标签: c# regex xml replace

我正在寻找从XML文件中删除空元素,因为读者需要一个值。它不是零xsi:nil="true"或没有内容<Element /> Deserialize Xml with empty elements in C#的元素。但是内部部分缺少的元素<Element></Element>

我已经尝试编写自己的代码来删除这些元素,但我的代码太慢而文件太大了。每个项目的结尾也将包含此模式。因此,以下正则表达式将删除有效的xml:
@"<.*></*>

我需要某种正则表达式,以确保两个*的模式是相同的。

所以:

<Item><One>1</One><Two></Two><Three>3</Three></Item>

会变成:

<Item><One>1</One><Three>3</Three></Item>

因此,这一切都是一行的事实使得这更难,因为这意味着项目的结尾是在三结束之后,产生了我想要寻找的模式。

我无法访问允许重新创建有效xml的原始数据。

3 个答案:

答案 0 :(得分:1)

您希望在< ... >capture word characters一个或多个See demo at regex101,并使用\1反向引用匹配结束标记第一组捕获的内容。

<(\w+)></\1>

{{3}}

答案 1 :(得分:1)

AFAIK 无需捕获任何群组,因为<a></b>(与未捕获的简单正则表匹配)只是无效的XML ,它可以&# 39;在你的文件中(除非你在这种情况下解析HTML - 即使可以完成 - 我建议不要使用正则表达式)。只有在您匹配非空节点时才需要捕获组,但不是您的情况。

请注意,您的正则表达式存在问题(除了未转义的 / ),因为您将任何字符匹配。但它不允许在XML标记中包含任何字符。如果您绝对想要使用.*,那么它应该是.*?,您应该排除 /

我要做的是保持正则表达式尽可能简单(仍然匹配有效的XML节点名称,或者 - 甚至更好 - 只有你知道的数据输入):

<\w+><\/\w+>

您应该/可以更好地检查标记名称,例如\s*[\w\d]+\s*可能会稍好一些,对于非常大的文件,使用较少步骤的正则表达式执行更好。您还可以在开始和结束标记之间添加可选的换行符。

请注意,您可能需要循环直到不再进行替换,例如,如果您有<outer><inner></inner></outer>并且您希望将其缩减为空字符串(特别是在这种情况下请勿忘记)编译你的正则表达式。)

答案 2 :(得分:0)

使用XML Linq

string xml = "<Item><One>1</One><Two></Two><Three>3</Three></Item>";
            XElement item = XElement.Parse(xml);
            item = new XElement("Item", item.Descendants().Where(x => x.Value.Length != 0));