2010-09-12 6 views
6

Necesito mover los nodos hermanos antes y después de ciertos nodos. Aquí está el código estoy trabajando conLINQ to XML: Cuál es la forma más efectiva de mover nodos hacia arriba y hacia abajo

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

Me gustaría mover la pestaña con las pruebas en él arriba Descripción. ¿Cómo voy a hacer esto usando linq a XML?

+1

¿Cuáles son las reglas para las cuales se mueve el nodo hermano antes/después de qué nodo? ¿O solo estás preguntando cómo mover los nodos? – dtb

+0

Eso es exactamente lo que necesito. Necesito saber cómo mover los nodos. Gracias – Luke101

Respuesta

2

Lo sentimos, esto es VB.NET y XML Literals, pero se puede hacer la vieja escuela en C#. La idea aquí es utilizar el método Reverse extensión:

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 
+0

wow ... después de leer esto varias veces, veo que esta es la manera más elegante de resolver este problema. Lo siento, ya he elegido la respuesta. Implementé tu solución en su lugar. Gracias – Luke101

+0

Feliz de ayudar a Luke101 –

+0

¿Qué pasa si los dos elementos no son adyacentes entre sí? – dtb

3

Puede mover los elementos mediante la eliminación de ellos y luego volver a colocarlas en la posición deseada:

var doc = XDocument.Parse(@"<tabs>...</tabs>"); 

var tab = doc.Root.Elements().ElementAt(1); 
tab.Remove(); 
doc.Root.AddFirst(tab); 

Como alternativa, puede crear un nuevo documento a partir de los elementos existentes en el orden deseado:

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))); 

yo no lo he probado, pero esto podría funcionar:

void Swap(XElement a, XElement b) 
{ 
    var c = new XElement("dummy"); 
    a.ReplaceWith(c); 
    b.ReplaceWith(a); 
    c.ReplaceWith(b); 
} 
+0

No estoy realmente interesado en mover nodos a la primera o la última posición. Simplemente quiero intercambiar nodos. ¿Cómo cambiaría Testing and Performance si la pestaña actual es Testing? – Luke101

+0

Además, su ejemplo asume que sé cuántos hermanos hay? Si no sé cuántos hermanos hay, pero sé que el elemento de prueba existe en algún lugar de los hermanos, ¿cómo puedo intercambiar estos elementos? – Luke101

+0

@ Luke101: He agregado una solución para cambiar a XElements arbitrarios en un XDocument. Aunque no lo he probado. – dtb

1

Usted puede usar algo como:

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); 

No está seguro de qué parte de su estructura XML es fija/conocido.

+0

Creo que este código mueve las pruebas a la primera posición. Ahora, ¿cómo cambiaría las pruebas de intercambio y el rendimiento? Realmente no soy interesante para mover nodos a la base o el último lugar, simplemente quiero intercambiar nodos. ¿Cómo puede hacerse esto? – Luke101

1

Sé que este post es viejo, pero se le ocurrió la misma edición de hoy y terminan resolviendo de esta manera:

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 
      } 
     } 
    } 
Cuestiones relacionadas