首页 > 解决方案 > 如何转换 XDocument 只留下选定的路径?

问题描述

我有很多(数百万)xml 文档,从小到大。我需要通过 c#7 处理(转换)它们,只留下一些路径(路径可能会有所不同;它们将由用户设置)。

一份文件的样本(我现在不关心命名空间):

<root>
<a><aa1></aa1><aa2></aa2></a>
<b><bb></bb></b>
<c><cc></cc></c>
<d>d</d>
</root>

给定/root/a/aa1并且/root/d被列入白名单我应该产生这个结果:

<root>
<a><aa1></aa1></a>
<d>d</d>
</root>

我想最好的方法是将白名单路径指定为 XPath 表达式的集合。

现有处理将 xml 加载到 XDocument 中。

我可以通过 选择必要的元素XPathSelectElements。问题是:如何将它们复制到新的 XDocument 中?

或者,我可以删除所选元素的所有兄弟姐妹。如何执行该删除?

应考虑性能和内存占用。

标签: c#xml

解决方案


尝试以下算法:

(a) 扩展给定的路径集以包括这些路径的所有前缀,因此从 ( /root/a/aa1, /root/d) 你得到 ( /root, /root/a, /root/a/aa1, /root/d)

(b) 从这组路径生成一个 XSLT 样式表,其中 (i) 默认模板规则执行深度跳过 ( <xsl:template match="*"/>),并且 (ii) 每个给定路径的模板规则执行浅拷贝 ( <xsl:copy><xsl:copy-of select="@*"/><xsl:apply-templates/></xsl:copy>)。

(c) 在源文档上运行这个生成的样式表。

您可能会发现在 XPath 3.1/XSLT 3.0 中可以使用 EQName 表示法来处理命名空间敏感路径很有用,例如 match="Q{some-uri}root/Q{some-uri}a"。对于早期的 XPath 版本,处理引用命名空间元素名称的路径总是一个问题。这同样适用于非 XSLT 解决方案。


推荐阅读