代码之家  ›  专栏  ›  技术社区  ›  Luke101

LINQ到XML:上下移动节点最有效的方法是什么

  •  6
  • Luke101  · 技术社区  · 14 年前

    我需要在某些节点前后移动同级节点。这是我正在使用的代码

    <tabs>
         <tab>
              <name>Overview</name>
         </tab>
         <tab>
              <name>Testing</name>
         </tab>
         <tab>
              <name>Performance</name>
         </tab>
         <tab>
              <name>Braking</name>
         </tab>
    </tabs>
    

    4 回复  |  直到 14 年前
        1
  •  2
  •   Todd Main    14 年前

    对不起,这是VB.NET版和XML文本,但它可以在C#中进行。这里的想法是使用 Reverse 扩展方法:

    Sub Main()
            Dim tab = <tabs>
                          <tab>
                              <name>Overview</name>
                          </tab>
                          <tab>
                              <name>Testing</name>
                          </tab>
                          <tab>
                              <name>Performance</name>
                          </tab>
                          <tab>
                              <name>Braking</name>
                          </tab>
                      </tabs>
            Console.WriteLine(SwapElements("Testing", "Performance", tab).ToString)
            Console.ReadLine()
        End Sub
        Function SwapElements(ByVal firstElement As String, ByVal secondElement As String, ByVal tab As XElement) As XElement
            Dim swapped = tab.Elements.Where(Function(e) e.Value = firstElement Or e.Value = secondElement).Reverse
            Dim middle = tab.Elements.SelectMany(Function(e) e.ElementsAfterSelf.Where(Function(f) e.Value = firstElement).TakeWhile(Function(g) g.Value <> secondElement))
            swapped.ElementAt(0).AddAfterSelf(middle)
            Return <<%= tab.Name %>>
                       <%= tab.Elements.Select(Function(e) e.ElementsBeforeSelf.Where(Function(f) e.Value = firstElement)) %>
                       <%= swapped %>
                       <%= tab.Elements.Select(Function(e) e.ElementsAfterSelf.Where(Function(f) e.Value = secondElement)) %>
                   </>
        End Function
    
        2
  •  3
  •   dtb    14 年前

    var doc = XDocument.Parse(@"<tabs>...</tabs>");
    
    var tab = doc.Root.Elements().ElementAt(1);
    tab.Remove();
    doc.Root.AddFirst(tab);
    

    或者,可以按所需顺序从现有元素创建新文档:

    var doc = XDocument.Parse(@"<tabs>...</tabs>");
    
    var tabs = doc.Root.Elements();
    
    var result = new XDocument(
                     new XElement("tabs", 
                         tabs.ElementAt(1),
                         tabs.ElementAt(0),
                         tabs.ElementAt(2)));
    

    我还没测试过,但这可能有用:

    void Swap(XElement a, XElement b)
    {
        var c = new XElement("dummy");
        a.ReplaceWith(c);
        b.ReplaceWith(a);
        c.ReplaceWith(b);
    }
    
        3
  •  1
  •   Henk Holterman    14 年前

        var tests = from node in doc.Descendants("name") where node.Value == "Testing" select node;
        var test = tests.Single();
        var tab = test.Parent;
        var tabs = tab.Parent;
        tab.Remove();
        tabs.AddFirst(tab);
    

    不确定有多少XML结构是固定的/已知的。

        4
  •  1
  •   dark_amadeus7    10 年前

    我知道这个帖子很老了,但我今天也提出了同样的问题,最后解决了这个问题:

    private void SwapXNodes(bool up, int inUniqueID)
        {
            XElement currNode = DocumentManager.xMainDocument.XPathSelectElement("//*[@UniqueID='" + inUniqueID + "']"); // find 
    
            if (up)
            {
                if (currNode.PreviousNode != null)
                {
                    XElement xPrevious = new XElement((XElement)currNode.PreviousNode); // copy of previous node
    
                    currNode.PreviousNode.ReplaceWith(currNode); // previous node equal to me
                    currNode.ReplaceWith(xPrevious); // Now I should be equal to previous node
                }
            }
            else
            {
                if (currNode.NextNode != null)
                {
                    XElement xNext = new XElement((XElement)currNode.NextNode); // copy of Next node
    
                    currNode.NextNode.ReplaceWith(currNode); // Next node equal to me
                    currNode.ReplaceWith(xNext); // Now I should be equal to Next node copy
                }
            }
        }