2011-03-05 10 views
7

Uso de rapidxml Estoy queriendo recorrer un conjunto de nodos, y estoy usando lo que encontré para ser la mejor manera de hacerlo (desde el stackoverflow de confianza, el documento no parece tener un ejemplo de iteración):rapidxml: ¿cómo iterar a través de los nodos? Deja fuera a último hermano

while (curNode->next_sibling() !=NULL) { 
    string shiftLength = curNode->first_attribute("shiftLength")->value(); 
    cout << "Shift Length " << "\t" << shiftLength << endl; 
    curNode = curNode->next_sibling();   
} 

por desgracia, en mi OSX 10.6 esto es dejando fuera el último nodo hermano - supongo que porque en la última iteración del bucle, next_sibling se llama dos veces. Puedo conseguir en este último nodo si escribo, después del bucle:

cout << " LAST IS: " << curNode->first_attribute("shiftLength")->value(); 

... pero eso es poco fiable, y el programa se cierra en ese punto.

Primera pregunta: ¿Podría ser esto un fallo único de mi configuración (OSX 10.6) o he codificado mal?

Segunda pregunta: ¿Alguien tiene un ejemplo de lo que creen que es la forma correcta de iterar a través de un número desconocido de nodos XML utilizando rapidxml?

Gracias chicos

Pete

+1

Piense en bucles en términos de invariantes. El suyo se ejecuta para todos los nodos con los próximos hermanos que no sean NULL. Esto no es cierto para el último nodo. –

Respuesta

1
while (curNode->next_sibling() !=NULL) 

Esto dice "mientras que hay un nodo más a la izquierda después de la que estoy trabajando en". Es por eso que su ciclo se detiene temprano - cuando curNode es el último hermano, su "next_sibling" será NULO. Esta prueba debe funcionar mejor:

while (curNode !=NULL) 
+0

Gracias Neil (Probé ese enfoque antes, pero obtuve un MAL ACCESO en rapidxml.hpp (línea 1031 contra 1.13) - aaaaggghh, aunque había intentado buscar un atributo después de que el ciclo había terminado). Gracias de nuevo. –

5

Aquí está el código final en forma de trabajo:

while(curNode != NULL) { 

    string start = curNode->first_attribute("start")->value(); 
    string numStaff = curNode->first_attribute("numStaff")->value(); 
    cout << start << "\t" << numStaff << endl; 
    curNode = curNode->next_sibling(); 
} 
11

Ésta es la forma correcta de iterar aunque todos los nodos hijos de un nodo en rapidxml:

xml_node<> *node = ... 
for (xml_node<> *child = node->first_node(); child; child = child->next_sibling()) 
{ 
    // do stuff with child 
} 
+0

Esto no es conveniente si está a punto de elegir un nodo aleatorio (por ejemplo, necesita saber la cantidad de nodos y elegir uno en la compensación X) –

+0

@Tomas Siempre hay una compensación en las estructuras de datos. Para permitir una adición rápida durante el análisis, rapidxml usa listas enlazadas para nodos secundarios y atributos. Por lo tanto, la indexación directa por número no es posible. Pero debes recordar que rapidxml no se trata de conveniencia sino de rendimiento. – kaalus

+0

He escrito una [función que le proporciona (a costo de ejecución) 'std :: vector' lleno de nodos secundarios] (https://gist.github.com/Darker/4b1ad792ff77a6688388). Tan pronto como se altera el árbol de documentos, la lista no es válida. –

Cuestiones relacionadas