代码之家  ›  专栏  ›  技术社区  ›  Anton Krouglov

如何转换XDocument,只留下选定的路径?

  •  0
  • Anton Krouglov  · 技术社区  · 6 年前

    一个文档的示例(我现在不关心名称空间):

    <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>
    

    现有处理将XML加载到XDocuments中。

    XPathSelectElements . 问题是:如何将它们复制到新的XDocument中?

    或者,我可以删除所选元素的所有同级。如何执行删除?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Michael Kay    6 年前

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

    <xsl:template match="*"/> <xsl:copy><xsl:copy-of select="@*"/><xsl:apply-templates/></xsl:copy> ).

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

        2
  •  0
  •   Anton Krouglov    6 年前

    这将删除非白名单节点,从而压缩XML文档:

    /// <summary> Siblings including self </summary>
    public static IEnumerable<XElement> Siblings(this XElement xml) =>
        xml?.Parent?.Elements() ?? new List<XElement>();
    
    /// <summary> Ancestors, descendants and self </summary>
    public static IEnumerable<XElement> AncestorsDescendantsSelf(this XElement xml) =>
        xml?.DescendantsAndSelf()?.Union(xml?.Ancestors() ?? new List<XElement>()) ?? new List<XElement>();
    
    /// <summary> Compress the document by removing everything except the elemnents along selected paths </summary>
    /// <param name="xml">source document to be modified</param>
    /// <param name="whitelistedPaths">collection of xpath paths</param>
    public static void Compress(this XDocument xml, IEnumerable<string> whitelistedPaths) {
        var siblings = nodes.SelectMany(n => n.AncestorsAndSelf()).Aggregate((new List<XElement>()).AsEnumerable(), (n1,n2) => n1.Union(n2.Siblings()));
        var lineages = nodes.SelectMany(n => n.AncestorsDescendantsSelf());
        var nodesToDelete = siblings.Except(lineages).ToList();
        foreach (var element in nodesToDelete) {
            element.Remove();
        }
    }
    

    注: 这段代码远不是很快/完美,但它只是工作。