2011-10-17 9 views
6

He estado tratando a buscar valores de texto de nodo de este archivo XML:Extracción de valores de nodo secundario con QXmlItem como QXmlQuery centran

<!DOCTYPE structure> 
    <data> 
    <x> 
    <id>1</id> 
    <nam>tytuł</nam> 
    <tab>21</tab> 
    <ind>5</ind> 
    <pre>TY</pre> 
    <khw>C.TY</khw> 
    </x> 
    <x> 
    <id>2</id> 
    <nam>autor</nam> 
    <tab>21</tab> 
    <ind>5</ind> 
    <pre>FO</pre> 
    <khw>C.FO</khw> 
    </x> 
    <x> 
    <id>3</id> 
    <nam>hasło korporatywne</nam> 
    <tab>21</tab> 
    <ind>5</ind> 
    <pre>FN</pre> 
    <khw>C.FN</khw> 
    </x> 
    </data> 

Lo que quiero hacer es ir a buscar todos los nodos y de los niños y convertir a QMap. No tengo problemas para obtener un solo elemento, pero cuando se trata de obtener elementos secundarios estableciendo el resultado de QXmlQuery como foco, el QString que evalúo la consulta del nodo secundario está vacío. Yo uso este trozo de código:

QXmlResultItems results; 
QFile structure("./structure.xml"); // xml file, as described earlier 
structure.open(QFile::ReadOnly); 

QXmlQuery query; 
query.setFocus(&structure); 
query.setQuery("data/x"); 
query.evaluateTo(&results); 

QXmlItem next = results.next(); 
while(!next.isNull()) { 
    qDebug() << next.toNodeModelIndex().stringValue(); // everything's fine. It prints contents of <x>'s child nodes 
    QXmlQuery childQuery; 
    QString r; 
    childQuery.setFocus(next); 
    childQuery.setQuery("./nam/text()"); // already tested: "/nam/text()", "/nam/string()", "x/nam/string()", "data/x/nam/string()" etc... still no luck. 
    childQuery.evaluateTo(&r); 
    qDebug() << r; // prints \n but it should print content of <nam> node. 

    next = results.next(); 
} 

software que utilizo: Qt SDK 4.7.2 directamente desde el sitio web de Qt, QtCreator 2.3.1 en Windows y Linux (sin ninguna diferencia en este caso particular, los resultados son los mismos) . Quiero estar seguro de que es el problema de mi falta de conocimiento, en lugar de error de software, por favor ayuda

+0

Lo curioso es que funciona con" ./ id/string() "o incluso con" ./name/string() "si cambia el nombre de las etiquetas" nam "a" nombre ". – alexisdm

+0

Parece el mismo problema que se describe aquí http://qt-project.org/forums/viewthread/25725 – CAMOBAP

Respuesta

0

Se debe trabajar de esta manera:

QDomDocument doc("structure"); 
QFile file("structure.xml"); 
if(!file.open(IO_ReadOnly)) 
    return -1; 
if(!doc.setContent(&file)) 
{ 
    file.close(); 
    return -2; 
} 
file.close(); 

QDomElement root = doc.documentElement(); 
if(root.tagName() != "data") 
    return -3; 

QDomNode n = root.firstChild(); 
while(!n.isNull()) 
{ 
    QDomElement e = n.toElement(); 
    if(!e.isNull()) 
    { 
    if(e.tagName() == "x") 
    { 
     QMessageBox::information(0, "X", e.attribute("id", "")+ "\n" + e.attribute("nam", "") + "\n" + e.attribute("tab", "")); 
    } 
    } 

    n = n.nextSibling(); 
} 

El código está haciendo un cuadro de mensaje para cada x (Don no tiene qt en esta máquina, por lo que no puede probarlo en este momento)

+0

Me temo que el método 'attribute()' es para obtener un atributo para un elemento específico, no para recuperar sus elementos secundarios. En ese caso particular, debería usar 'firstChild(). NodeValue()' en la variable 'e'. Sé que podría usar este enfoque, pero lo que quería evitar es demasiado código para obtener datos particulares del árbol XML. –

1

En lugar de usar evaluateTo(QString *), utilice la versión QStringList. Deberia de funcionar.

+0

Ahora funciona. ¿Podría explicar por qué debería funcionar? – CAMOBAP

0

Tuve el mismo problema, y ​​la solución fue que el query y el childQuery fueran exactamente iguales. Se podría volver a escribir el código como:

while(!next.isNull()) { 
    qDebug() << next.toNodeModelIndex().stringValue(); 
    QString r; 
    query.setFocus(next); 
    query.setQuery("./nam/text()"); 
    query.evaluateTo(&r); 
    qDebug() << r; 

    next = results.next(); 
} 

si childQuery es estar en otro procedimiento, usted tiene que pasar por referencia.

7

Por desgracia, no está claro a partir de documentación de Qt que en los casos cuando se desea utilizar QXmlQuery::setFocus(const QXmlItem& item) sobrecarga con el fin de consultar los nodos secundarios, se debe crear objetos utilizando correspondiente QXmlQueryQXmlQuery(const QXmlNamePool& np) constructor para hacer que ellos comparten la misma QXmlNamePool objeto. Tal intercambio, simplemente hablando, relaciona las consultas entre sí.

Teniendo en cuenta esto, su ejemplo debería parecerse a lo siguiente:

QFile structure("./structure.xml"); 
structure.open(QFile::ReadOnly); 

QXmlQuery query; 
query.setFocus(&structure); 
query.setQuery("data/x"); 

QXmlResultItems results; 
query.evaluateTo(&results); 

QXmlQuery childQuery(query.namePool()); 
while (!results.next().isNull()) { 
    childQuery.setFocus(results.current()); 
    childQuery.setQuery("nam/text()"); 
    QString r; 
    childQuery.evaluateTo(&r); 
    qDebug() << r; 
} 

Por otra parte, se puede ir más allá y reutilizar inicial QXmlQuery objeto:

QFile structure("./structure.xml"); 
structure.open(QFile::ReadOnly); 

QXmlQuery query; 
query.setFocus(&structure); 
query.setQuery("data/x"); 

QXmlResultItems results; 
query.evaluateTo(&results); 

while (!results.next().isNull()) { 
    query.setFocus(results.current()); 
    query.setQuery("nam/text()"); 
    QString r; 
    query.evaluateTo(&r); 
    qDebug() << r; 
} 
Cuestiones relacionadas