2011-10-17 9 views
6

Ho cercato di recuperare i valori di testo dei nodi da questo file XML:Estrazione valori di nodi figlio con QXmlItem come QXmlQuery concentrano

<!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> 

Quello che voglio fare è quello di prendere ogni nodo e per bambini e convertire a QMap. Non ho problemi con il recupero di un singolo elemento, ma quando si tratta di recuperare elementi figli impostando come risultato il risultato di QXmlQuery, il QString che valuto la query del nodo figlio è vuoto. Io uso questo pezzo di codice:

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 che uso: Qt 4.7.2 SDK direttamente dal sito Qt, QtCreator 2.3.1 su Windows e Linux (senza alcuna differenza in questo caso particolare, i risultati sono gli stessi) . Voglio essere sicuro che sia il problema della mia mancanza di conoscenza, piuttosto che bug del software, si prega di aiutare

+0

La cosa divertente è che funziona con" ./ id/string() "o anche con" ./name/string() "se si rinominano i tag" nam "in" name ". – alexisdm

+0

Sembra lo stesso problema descritto qui http://qt-project.org/forums/viewthread/25725 – CAMOBAP

risposta

0

Dovrebbe funzionare in questo modo:

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

Il codice sta facendo una finestra di messaggio per ogni x (don 't avere qt su questa macchina, quindi non può testarlo in questo momento)

+0

Ho paura che il metodo 'attribute()' sia per il recupero di attributi per elementi specifici, non per il recupero dei suoi figli. In quel caso particolare dovrei usare 'firstChild(). NodeValue()' sulla variabile 'e'. So che potrei usare questo approccio, ma quello che volevo evitare è troppo codice per recuperare particolari dati dall'albero XML. –

1

Invece di utilizzare evaluateTo(QString *) utilizzare la versione QStringList. Dovrebbe funzionare.

+0

Ora lavoro. Potresti spiegare, perché dovrebbe funzionare? – CAMOBAP

0

Ho avuto lo stesso problema e la soluzione era di avere il query e childQuery esattamente lo stesso. Si potrebbe riscrivere il codice come:

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

    next = results.next(); 
} 

se childQuery è quello di essere in un altro procedimento, devi passare per riferimento.

7

Purtroppo, non è chiaro da Qt documentazione che nei casi in cui si desidera utilizzare QXmlQuery::setFocus(const QXmlItem& item) sovraccarico al fine di interrogare nodi figlio, è necessario creare corrispondente QXmlQuery oggetti utilizzando QXmlQuery(const QXmlNamePool& np) costruttore per farli condividere lo stesso QXmlNamePool oggetto. Tale condivisione, semplicemente parlando, riguarda le query l'una con l'altra.

Considerando questo, il vostro esempio dovrebbe apparire come segue:

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

Inoltre, si può andare oltre e riutilizzare iniziale QXmlQuery oggetto:

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; 
} 
Problemi correlati