如何过滤xml部分并将其另存为文件

时间:2011-01-16 10:15:31

标签: c# linq linq-to-xml

我是使用LINQ的初学者。我有一个格式如下的xml数据

<Root>
    <Global>
    </Global>
    <local>
        <element name="A">
            <subelement name="A">
                <element name="A1">
                    <subelement name="A1">
                        <Property>
                        </Property>
                    </subelement>
                </element>
                <element name="B">
                    <Property>
                    </Property>
                </element>
            </subelement>
            <subelement name="B">
                <element name="A">
                    <Property>
                    </Property>
                </element>
                <element name="B">
                    <Property>
                    </Property>
                </element>
            </subelement>
        </element>
    </local>
</Root>

我想将 Property 元素的每个部分保存到它自己的xml文件中,如下所示,同时保持层次结构完整

<Root>
    <Global>
    </Global>
    <local>
        <element name="A">
            <subelement name="A">
                <element name="A1">
                    <subelement name="A1">
                        <Property>
                        </Property>
                </subelement>
                </element>
            </subelement>
        </element>
    </local>
</Root>

<Root>
    <Global>
    </Global>
    <local>
        <element name="A">
            <subelement name="A">
                <element name="B">
                    <Property>
                    </Property>
                </element>
            </subelement>
        </element>
    </local>
</Root>
所有 Property 元素的

等等。每个元素都可以包含子子元素,每个子元素可以包含元素子元素

您是否可以提供有关如何将 Property 元素的每个部分保存为新xml文件的解决方案,其中当前层次结构保持不变。我尝试使用XElement类的Ancestor()方法

XDocument xml = XDocument.Load(filename);
XDocument convertedQuery = new XDocument(
        new XElement(xml.Root.Name, from x in xml.Descendants("local")
                                    select x.Ancestors())
         );

但它也会返回其他 Property 元素,如下所示

<Root>
<Global></Global>
<local>
  <element name="A">
    <subelement name="A">
      <element name="A1">
        <subelement name="A1">
          <Property></Property>
        </subelement>
      </element>
      <element name="B">
        <Property></Property>
      </element>
    </subelement>
    <subelement name="B">
      <element name="A">
        <Property></Property>
      </element>
      <element name="B">
        <Property></Property>
      </element>
    </subelement>
  </element>
</local>

非常感谢任何帮助。感谢

1 个答案:

答案 0 :(得分:2)

这是一些C#示例应该做你想要的,或者至少让你知道如何处理它。用于测试的示例只是将每个创建的XDocument写入Console.Out,但当然您可以将其更改为保存到磁盘上的文件:

static void Main(string[] args)
{
    XDocument doc = XDocument.Load(@"..\..\XMLFile1.xml");
    foreach (XElement prop in doc.Descendants("Property"))
    {
        XDocument result = new XDocument(
            new XElement(doc.Root.Name, doc.Root.Attributes(),
                doc.Root.Elements("Global"),
                CopySubtree(prop.Ancestors("local").First(), prop)));
        result.Save(Console.Out);
        Console.WriteLine();
    }
}
static XElement CopySubtree(XElement ancestor, XElement descendant)
{
    if (ancestor == descendant)
    {
        return descendant;
    }
    else
    {
        return
            new XElement(
                ancestor.Name, 
                ancestor.Attributes(), 
                CopySubtree(
                  ancestor
                  .Elements()
                  .First(e => e.DescendantsAndSelf().Any(d => d == descendant)),
                  descendant));
    }
}

[编辑] 对于不仅要复制属性祖先而且复制其兄弟姐妹的新要求,您可以按照以下方法进行调整:

static XElement CopySubtree(XElement ancestor, XElement descendant)
{
    if (ancestor == descendant.Parent)
    {
        return ancestor;
    }
    else
    {
        return
            new XElement(
                ancestor.Name, 
                ancestor.Attributes(), 
                CopySubtree(
                  ancestor
                  .Elements()
                  .First(e => e.DescendantsAndSelf().Any(d => d == descendant)),
                  descendant));
    }
}