2011-10-17 42 views
6

我一直在試圖從這個XML文件讀取節點文本值:提取與QXmlItem子節點的值作爲QXmlQuery重點

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

我想要做的就是獲取每一個節點,它是兒童和轉換它到QMap。我在獲取單個元素時沒有問題,但是當通過將QXmlQuery的結果設置爲焦點來獲取子項時,我計算子節點查詢的QString是空的。我使用這段代碼:

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

軟件我用:4.7.2 SDK直接從Qt的網站,在Windows和Linux 2.3.1 QtCreator QT(沒有這種特殊的情況下,任何的區別,結果都是一樣的) 。我想肯定這是我的知識缺乏的問題,而不是軟件錯誤,請大家幫忙

+0

有趣的是,它與」 ./如果您將「nam」標記重命名爲「name」,那麼甚至可以使用「./name/string()」。 – alexisdm

+0

看起來像這裏描述的相同的問題http://qt-project.org/forums/viewthread/25725 – CAMOBAP

回答

0

它應該是這樣的:

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

的代碼做一個消息框,每X(唐在這臺機器上沒有qt,所以現在不能測試)

+0

恐怕'attribute()'方法是爲特定元素獲取屬性,而不是用於獲取其子元素。在這種情況下,我應該在變量'e'上使用'firstChild()。nodeValue()'。我知道我可以使用這種方法,但是我想避免的是從XML樹中獲取特定數據的代碼過多。 –

1

而不是使用evaluateTo(QString *)使用QStringList版本。它應該工作。

+0

現在工作。你能解釋一下,爲什麼它應該工作? – CAMOBAP

0

我有同樣的問題,解決方案是讓querychildQuery完全相同。你可以重寫你的代碼爲:

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

    next = results.next(); 
} 

如果childQuery是要在另一個程序,你必須按引用傳遞它。

7

不幸的是,它是從Qt文檔尚不清楚的情況下,當你想使用QXmlQuery::setFocus(const QXmlItem& item)超載以便查詢子節點,您應該創建相應的使用QXmlQuery(const QXmlNamePool& np)構造,使他們共享同一個QXmlNamePool對象QXmlQuery對象。這種分享,簡單地說,涉及彼此的查詢。

考慮到這一點,你的榜樣應該像下面:

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

此外,你可以走得更遠和重用初始QXmlQuery對象:

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