C#返回一个包含祖先和self的XML元素,但不返回其他子元素

C#返回一个包含祖先和self的XML元素,但不返回其他子元素,c#,xml,linq,linq-to-xml,C#,Xml,Linq,Linq To Xml,我有这样一个xml文档布局 <?xml version="1.0" encoding="utf-8" ?> <Document name="document name"> <DataSet name="dataset 1"> <Dimension name="dimension 1"> <Metric name="metric 1"> <Data va

我有这样一个xml文档布局

<?xml version="1.0" encoding="utf-8" ?>
<Document name="document name">
    <DataSet name="dataset 1">
        <Dimension name="dimension 1">
            <Metric name="metric 1">
                <Data value="1">
                <Data value="2">
                <Data value="3">
            </Metric>
            <Metric name="metric 2">
                <Data value="4">
                <Data value="5">
                <Data value="6">
            </Metric>
        </Dimension>
        <Dimension name="dimension 2">
            <Metric name="metric 3">
                <Data value="6">
                <Data value="7">
                <Data value="8">
            </Metric>
            <Metric name="metric 4">
                <Data value="9">
                <Data value="10">
                <Data value="11">
            </Metric>
        </Dimension>
    </DataSet>
</Document>
还要注意的是,如果我使用下面的代码,我会得到我要寻找的确切指标,但我需要将它们封装在它们的父级中

IEnumerable<XElement> elementsInPath = doc.Descendants(elementName)
                                                        .Where(p => p.Attribute(attributeName).Value.Contains(attributeValue))
                                                        .InDocumentOrder()
                                                        .ToList();
IEnumerable elementsInPath=doc.substands(elementName)
.Where(p=>p.attributeName.Value.Contains(attributeValue))
.InDocumentOrder()
.ToList();

因此,您实际上是在为每个
指标
元素构建一个新文档。最直接的方法是:

foreach (XElement el in doc.Root.Descendants("Metric"))
{
    XElement newDoc =
        new XElement("Document",
            new XAttribute(doc.Root.Attribute("name")), 
            new XElement("DataSet", 
                new XAttribute(el.Parent.Parent.Attribute("name")),
                new XElement("Dimension", 
                    new XAttribute(el.Parent.Attribute("name")), 
                    el)
                )
            )
        );
    newDoc.Save(el.Attribute("name").Value.Replace(" ", "_") + ".xml");
}
这很有希望地说明了动态版本的工作原理——遍历祖先并基于它们创建新元素:

foreach (XElement el in doc.Root.Descendants("Metric"))
{
    XElement newDoc = el;
    foreach(XElement nextParent in el.Ancestors()) // iterate through ancestors
    {
        //rewrap in ancestor node name/attributes
        newDoc = new XElement(nextParent.Name, nextParent.Attributes(), newDoc);
    }

    newDoc.Save(el.Attribute("name").Value.Replace(" ", "_") + ".xml");
}

仅仅使用
祖先()
功能是行不通的,因为当您尝试添加它们时,它也会添加它们的子元素(您尝试拆分的元素的兄弟姐妹)。

我正要问,如果没有
.anteStorsandself()
部分,您会得到什么,但您是有远见的:)是的,我的节点名称将是动态的。我有一个表单,它将采用elementName来搜索/拆分文档。因此,我需要一种方法以编程方式获取元素“metric”的所有父元素。我想我可以检索元素,然后在递归循环中不断请求其父元素,但我不知道如何重新构建文件。谢谢!这很有魅力。现在,我看到您使用原始文档中的名称和属性构建了一个新的父元素,这样就没有子元素了。对-这基本上就是我在“静态”版本中所做的,但是现在我已经设置了从父元素获取所有属性和名称。
                int i = 1;
                foreach (XElement element in elementsInPath)
                {
                    XDocument tmpDoc = new XDocument();
                    tmpDoc.Add(element);
                    tmpDoc.Save(outputDirectory + elementName + "_" + i + ".xml");
                    i++;
                }
IEnumerable<XElement> elementsInPath = doc.Descendants(elementName)
                                                        .Where(p => p.Attribute(attributeName).Value.Contains(attributeValue))
                                                        .InDocumentOrder()
                                                        .ToList();
foreach (XElement el in doc.Root.Descendants("Metric"))
{
    XElement newDoc =
        new XElement("Document",
            new XAttribute(doc.Root.Attribute("name")), 
            new XElement("DataSet", 
                new XAttribute(el.Parent.Parent.Attribute("name")),
                new XElement("Dimension", 
                    new XAttribute(el.Parent.Attribute("name")), 
                    el)
                )
            )
        );
    newDoc.Save(el.Attribute("name").Value.Replace(" ", "_") + ".xml");
}
foreach (XElement el in doc.Root.Descendants("Metric"))
{
    XElement newDoc = el;
    foreach(XElement nextParent in el.Ancestors()) // iterate through ancestors
    {
        //rewrap in ancestor node name/attributes
        newDoc = new XElement(nextParent.Name, nextParent.Attributes(), newDoc);
    }

    newDoc.Save(el.Attribute("name").Value.Replace(" ", "_") + ".xml");
}