2009-05-17 15 views
26

Necesito eliminar un XmlNode en función de una condición. ¿Cómo hacerlo?Cómo eliminar un XmlNode de XmlNodeList

foreach (XmlNode drawNode in nodeList) 
{ 
     //Based on a condition 
     drawNode.RemoveAll(); //need to remove the entire node      

} 
+0

¿Cuál es el problema con eso? –

Respuesta

4

No puede usar fácilmente los iteradores (foreach-statement) para eliminar sus nodos. Según lo veo, puede hacer lo siguiente:

1) En su ciclo de inicio, guarde una lista de todos los elementos que deben eliminarse. Luego recorres esos elementos y los eliminas.

2) Utilice un ciclo for ordinario y realice un seguimiento de cuál es el siguiente elemento para visitar después de haber eliminado un elemento.

Editar: Al usar un for-loop, hágalo de la manera que sugiere Fredrik, haciendo un círculo hacia atrás.

+1

Upvoting para la primera respuesta; la parte 2 suena un poco complicada de la manera en que la describes, por lo general es más fácil repetir la lista en orden inverso para que no tengas que preocuparte por el siguiente índice. – overslacked

+0

Por qué agregué "... una pista de seguimiento de la cual es el siguiente elemento para visitar ..." fue porque no sabía de qué manera se implementaría for-loop, si los nodos están en el orden correcto, etc. –

4

Si está intentando eliminar un nodo del XML DOM, esta no es la forma correcta. Porque XMLNodeList es solo una lista de nodos. En su lugar, desea eliminar el nodo del nodo principal. De esta manera:

XmlNode parentNode = // some value 
XmlNode drawNode = // some value 
parentNode.ParentNode.RemoveChild(drawNode); 
+1

AFIK , XmlNode "RemoveNode" no existe en C#. –

+1

De hecho, al menos a 4.0. Creo que quiso decir: drawNode.ParentNode.RemoveChild (drawNode); Es un poco feo pero hace lo que esperaría que hiciera una función de "eliminar": elimina el drawNode y cualquier cosa en él. – philw

+0

@philw - Creo que tienes razón. He editado la respuesta según corresponda –

57

Esto debería hacer el truco para usted:

for (int i = nodeList.Count - 1; i >= 0; i--) 
{ 
    nodeList[i].ParentNode.RemoveChild(nodeList[i]); 
} 

Si bucle que utiliza un cliente habitual, y el bucle for-loop sobre ella "hacia atrás" se puede eliminar elementos a medida que avanza.

Actualización: aquí es un ejemplo completo, incluyendo la carga de un archivo XML, la localización de los nodos, de borrarlos y guardando el archivo:

XmlDocument doc = new XmlDocument(); 
doc.Load(fileName); 
XmlNodeList nodes = doc.SelectNodes("some-xpath-query"); 
for (int i = nodes.Count - 1; i >= 0; i--) 
{ 
    nodes[i].ParentNode.RemoveChild(nodes[i]); 
} 
doc.Save(fileName); 
+0

¿No debería funcionar si también se ha enlazado? – devnull

+1

En este caso particular, funcionaría dado que el código no está eliminando los nodos de la colección XmlNodeList, sino del DOM de XmlDocument, pero en muchos otros casos, eliminar elementos en un bucle for anticipado puede dar resultados inesperados (como que los elementos no se eliminen remoto). Movimiento reflejo, supongo; o) –

+0

Este es el método iterativo ampliamente utilizado para eliminar elementos de colecciones. Gracias fredrik por el código de iluminación sabio a todos :) – Ravisha

1

no es el siguiente un poco más simple:

XmlDocument doc = new XmlDocument(); 
doc.Load(fileName); 
XmlNodeList nodes = doc.SelectNodes("some-xpath-query"); 
while (nodes.FirstChild != null) {  
    nodes.RemoveChild(nodes.FirstChild); 
} 
doc.Save(fileName); 
0
XmlNodeList xnodeContact = xmldocContact.GetElementsByTagName("contact"); 
      foreach (ListViewItem item in listViewContacts.Items) 
      { 
       if (item.Checked) 
       { 
        if (item.Index >= 0) 
         xnodeContact[0].ParentNode.RemoveChild(xnodeContact[0]); 
         listViewContacts.Items.Remove(item); 
        } 
       } 
      } 
      xmldocContact.Save(appdataPath + "\\WhatAppcontactList.xml"); 
      Invalidate();