C# 返回具有祖先和自身的 XML 元素,但没有其他 children

C# returning an XML element with ancestors and self, but no other children

我有一个 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>

我正试图将指标与他们的祖先分开,而不是与他们的兄弟姐妹分开。例如我想要一个文件看起来像...

<?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>
        </Dimension>
    </DataSet>
</Document>

文件 2 看起来像...

<?xml version="1.0" encoding="utf-8" ?>
    <Document name="document name">
        <DataSet name="dataset 1">
            <Dimension name="dimension 1">
                <Metric name="metric 2">
                    <Data value="4">
                    <Data value="5">
                    <Data value="6">
                </Metric>
            </Dimension>
        </DataSet>
    </Document>

我试图解决这个问题是创建一个方法来接受 xmlfile、outputDirectory、elementName、attributeName 和 attributeValue。

这将允许我在文档中搜索特定指标并将其与整个树一起提取到自己的文件中,但不能与其兄弟一起提取。

在我的方法的顶部,我有...

XDocument doc = XDocument.Load(xmlFile);

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

但是,当我遍历 elementsInPath 时,输出给出匹配的 "Metric" 的所有 parents 以及每个 parent return 的所有 children,我唯一想要的 child 是与输入参数匹配的那个。

如有任何帮助,我们将不胜感激。仅供参考,我使用以下代码段保存文件

                int i = 1;
                foreach (XElement element in elementsInPath)
                {
                    XDocument tmpDoc = new XDocument();
                    tmpDoc.Add(element);
                    tmpDoc.Save(outputDirectory + elementName + "_" + i + ".xml");
                    i++;
                }

另请注意,如果我使用以下代码,我会得到我正在寻找的确切指标,但我需要将它们封装在它们的 parent 中。

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

所以您实际上是在为每个 Metric 元素构建一个新文档。最直接的方法是:

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");
}

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