LINQ to XML: Какой самый эффективный способ перемещения узлов вверх и вниз - PullRequest
6 голосов
/ 12 сентября 2010

Мне нужно переместить узлы-братья до и после определенных узлов. Вот код, с которым я работаю

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

Я хотел бы переместить вкладку с тестированием в ней выше Обзор. Как бы я пошел по этому поводу, используя linq to XML?

Ответы [ 4 ]

3 голосов
/ 12 сентября 2010

Вы можете переместить элементы, удалив их, а затем снова вставив их в нужную позицию:

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);
}
2 голосов
/ 13 сентября 2010

Извините, это 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
1 голос
/ 26 января 2015

Я знаю, что этот пост старый, но сегодня я столкнулся с той же проблемой и в итоге решил ее следующим образом:

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
            }
        }
    }
1 голос
/ 12 сентября 2010

Вы можете использовать что-то вроде:

    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 является фиксированной / известной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...