【问题标题】:LINQ to XML Newbie: Moving Nodes From One Node To AnotherLINQ to XML 新手:将节点从一个节点移动到另一个节点
【发布时间】:2009-05-29 18:07:15
【问题描述】:

您好!

我有一个包含以下内容的 XElement 对象:

<Root>
    <SubSections>
        <SubSection id="A">
            <Foo id="1">
                <Bar />
                <Bar />
                <Bar />
            </Foo>
            <Foo id="2">
                <Bar />
                <Bar />
            </Foo>
            <Foo id="3">
                <Bar />
            </Foo>
        </SubSection>
        <SubSection id="B">
            <Foo id="4">
                <Bar />
                <Bar />
                <Bar />
            </Foo>
            <Foo id="5">
                <Bar />
                <Bar />
            </Foo>
         </SubSection>
        <SubSection id="C">

        </SubSection>
    </SubSections>
</Root>

我想将 Foo 的 2 和 3 移动到 id 为“C”的 SubSection,结果是:

<Root>
    <SubSections>
        <SubSection id="A">
            <Foo id="1">
                <Bar />
                <Bar />
                <Bar />
            </Foo>
        </SubSection>
        <SubSection id="B">
            <Foo id="4">
                <Bar />
                <Bar />
                <Bar />
            </Foo>
            <Foo id="5">
                <Bar />
                <Bar />
            </Foo>
        </SubSection>
        <SubSection id="C">
            <Foo id="2">
                <Bar />
                <Bar />
            </Foo>
            <Foo id="3">
                <Bar />
            </Foo>
        </SubSection>
    </SubSections>
</Root>

将 Foo 部分“2”和“3”移动到“C”子部分的最佳方法是什么?

【问题讨论】:

    标签: c# linq linq-to-xml


    【解决方案1】:

    您需要通过如下查询获取 Foo 第 2 和 3 节:

    var foos = from xelem in root.Descendants("Foo")
               where xelem.Attribute("id").Value == "2" || xelem.Attribute("id").Value == "3"
               select xelem;
    

    然后迭代该列表并将它们从其父母中删除

    xelem.Remove();
    

    然后只需将它们添加到正确的节点:

    parentElem.Add(xelem);
    

    第一个查询将获取两个部分,然后将每个部分删除并添加到树上的正确位置。

    这是一个完整的解决方案:

    var foos = (from xElem in xDoc.Root.Descendants("Foo")
                       where xElem.Attribute("id").Value == "2" || xElem.Attribute("id").Value == "3"
                       select xElem).ToList();
    
            var newParentElem = (from xElem in xDoc.Root.Descendants("SubSection")
                                where xElem.Attribute("id").Value == "C"
                                select xElem).Single();
    
            foreach(var xElem in foos)
            {
                xElem.Remove();
                newParentElem.Add(xElem);
            }
    

    之后,您的 xDoc 应该有正确的树。

    【讨论】:

    • 一些小的 cmets:.Value 是一个字符串,所以引用“2”和“3”。我相信您可以只调用 foos.Remove() 而不是迭代。虽然您可能需要在此之前复制 foos,因为 .Remove() 会清理 foos。
    • 你可能是对的。我想你可能只调用 foos.Remove() 然后调用 parentElem.Add(foos) 但我认为迭代会更好,然后你可以删除然后添加该元素,然后将 IEnumerable 移动到下一个元素.
    • 这会导致一个空的 parentElem 节点: var toMove = foos; foos.Remove(); parentElem.Add(toMove);这会杀死 Web 服务器(可能是因为它一遍又一遍地添加和删除同一个节点): var toMove = foos; parentElem.Add(toMove); foos.Remove();有什么想法吗?
    • 迭代可能更安全,但我发现不再编写 foreach 语句是一个挑战。 :) 而不是循环,尝试: newParentElem.Add(foos); foos.Remove();
    猜你喜欢
    • 2019-12-03
    • 2011-08-26
    • 1970-01-01
    • 2017-03-20
    • 2023-03-10
    • 2012-03-12
    • 2020-04-02
    • 2020-06-10
    • 1970-01-01
    相关资源
    最近更新 更多