【问题标题】:C# returning an XML element with ancestors and self, but no other childrenC# 返回具有祖先和自身但没有其他子元素的 XML 元素
【发布时间】:2016-02-02 13:16:54
【问题描述】:

我有一个这样的 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”的所有父级,每个父级返回其所有子级,而我想要呈现的唯一子级是与输入参数匹配的那个。

任何帮助将不胜感激。仅供参考,我使用以下 sn-p 保存文件

                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();

【问题讨论】:

  • 我正要问如果没有.AncestorsAndSelf() 部分你会得到什么,但你很有远见:)

标签: c# xml linq linq-to-xml


【解决方案1】:

因此,您实际上是在为每个 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() 功能是行不通的,因为当您尝试添加它们时,它也会添加它们的子元素(您尝试拆分的元素的兄弟姐妹)。

【讨论】:

  • 是的,我的节点名称将是动态的。我有一个表单,它将采用 elementName 来搜索/拆分文档。所以我需要一种以编程方式获取元素“度量”的所有父项的方法。我想我可以检索元素,然后在递归循环中继续询问其父元素,但我不知道如何备份文件。
  • 谢谢!这就像一个魅力。我现在看到您使用原始文档中的名称和属性构建了一个新的父元素,因此它没有子元素。
  • 对 - 这基本上是我在“静态”版本中所做的,但现在我可以从父元素中获取所有属性和名称。
猜你喜欢
  • 2019-06-10
  • 1970-01-01
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 2019-05-03
  • 1970-01-01
  • 2014-09-08
相关资源
最近更新 更多