使用LINQ to XML进行XML遍历,复制元素和节点

时间:2009-11-15 05:17:57

标签: linq-to-xml

我的XML文档如下 -

<?xml version="1.0" encoding="utf-8"?>
<Parents>
    <Parent id="A" description="A is a parent">
        <Children>
            <ChildName name = "Son1ofA" />
            <ChildName name = "Son2ofA" />
        </Children>
    </Parent>
</Parents>

要求 -

  1. 要识别元素“父”,请克隆它。将属性ID更改为“B”。将它添加为自己的兄弟(使其成为“父母”的新孩子)。
  2. 输出文件如下 -

    <Parents>
    <Parent id="A" description="A is a parent">
        <Children>
            <ChildName name = "Son" />
            <ChildName name = "Daughter" />
        </Children>
    </Parent>
    <Parent id="B" description="A is a parent">
        <Children>
            <ChildName name = "Son" />
            <ChildName name = "Daughter" />
        </Children>
    </Parent>
    

  3. 我的代码

    XDocument myXMLDocument = XDocument.Load("File.xml");
    XElement myParentsElement = myXMLDocument.Element("Parents");
    XElement myFirstParentElement = myParentsElement.Element("Parent");
    XElement myNewParentElement = new XElement(myFirstParentElement);
    XAttribute myParentId = myNewParentElement.Attribute("id");
    myParentId.Value = "B";
    myFirstParentElement.AddAfterSelf(myNewParentElement);
    myXMLDocument.Save("NewFile.xml");
    

    它完美无缺,没有任何问题。显然,这不是一个好的编程。因为,我正在提取Element Parents,然后使用它作为根节点,我正在提取Parent等,

    我希望能做的是这样的事情 - 直接键入路径 - 如在/ Parents / Parent(XPath)中,提取特定节点,制作它的副本,修改其属性,将其添加为兄弟并保存文档。

    我在做些傻事吗?

2 个答案:

答案 0 :(得分:3)

我不会说你正在做一些“愚蠢”的事情,但有一些方法可以克隆节点并使用LINQ以更简化的方式修改它。根据您的目标,您可以使用函数来修改节点和一些方便的LINQ表达式来克隆它。以下是基于您上面所做的一个示例:

        XDocument doc = XDocument.Parse(@"<?xml version='1.0' encoding='utf-8'?>
        <Parents>
            <Parent id='A' description='A is a parent'>
                    <Children>
                            <ChildName name = 'Son1ofA' />
                            <ChildName name = 'Son2ofA' />
                    </Children>
            </Parent>
        </Parents>
        ");

        Func<XElement, XElement> trans = (x) => {
            char c = Convert.ToChar(x.Attribute("id").Value);
            int inc = (int)c;
            x.Attribute("id").Value = Convert.ToChar(++inc).ToString();
            return x;
        };
        string elementTarget = "Parent"; // assume you read this from some input
        doc.Root.ReplaceWith(new XElement(doc.Root.Name,
                                doc.Descendants(elementTarget).Select(p => p),
                                doc.Descendants(elementTarget).Select(p => trans(p))));

        Console.Write(doc);
        Console.ReadLine();

您可以在“trans”匿名函数中看到转换的逻辑,以及使用LINQ中的 Descendants 枚举任意选择节点的能力。这个解决方案有些脆弱,但也许它可以给你一些想法。

答案 1 :(得分:2)

如果你想在Linq-to-xml中使用XPath,下面是一些有用的扩展方法。

using System.Xml.XPath;

XDocument.Load("file name").XPathSelectElement("XPath");