2011-10-17 15 views
6

Tôi đã cố gắng để lấy các giá trị văn bản nút từ file XML này:Extracting giá trị nút con với QXmlItem như một QXmlQuery tập trung

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

Những gì tôi muốn làm là để lấy tất cả các nút và nó là trẻ em và chuyển đổi nó đến QMap. Tôi không có rắc rối với lấy phần tử duy nhất, nhưng khi nói đến lấy trẻ em mục bằng cách thiết lập kết quả của QXmlQuery như là một tập trung, các QString rằng tôi đánh giá các truy vấn nút con là trống rỗng. Tôi sử dụng đoạn mã này:

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

phần mềm tôi sử dụng: Qt 4.7.2 SDK trực tiếp từ trang web của Qt, QtCreator 2.3.1 trên Windows và Linux (không có bất kỳ sự khác biệt trong trường hợp đặc biệt này, kết quả đều giống nhau) . Tôi muốn chắc chắn đó là vấn đề của tôi thiếu kiến ​​thức, chứ không phải là lỗi phần mềm, xin vui lòng giúp

+0

Điều buồn cười là nó hoạt động với" ./ id/string() "hoặc thậm chí với" ./name/string() "nếu bạn đổi tên các thẻ" nam "thành" name ". – alexisdm

+0

Dường như cùng một vấn đề được mô tả ở đây http://qt-project.org/forums/viewthread/25725 – CAMOBAP

Trả lời

0

Nó sẽ làm việc như thế này:

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

Mã này được thực hiện một hộp thông báo cho mọi x (don không có qt trên máy này, vì vậy không thể kiểm tra nó ngay bây giờ)

+0

Tôi sợ rằng phương thức 'attribute()' là tìm nạp thuộc tính cho phần tử cụ thể, không phải để tìm nạp các phần tử con của nó. Trong trường hợp cụ thể đó, tôi nên sử dụng 'firstChild(). NodeValue()' trên biến 'e'. Tôi biết rằng tôi có thể sử dụng cách tiếp cận này, nhưng những gì tôi muốn tránh là quá nhiều mã để lấy dữ liệu cụ thể từ cây XML. –

1

Thay vì sử dụng evaluateTo(QString *) sử dụng phiên bản QStringList. Nó sẽ hoạt động.

+0

Hiện đang hoạt động. Bạn có thể vui lòng giải thích, tại sao nó nên hoạt động? – CAMOBAP

0

Tôi gặp vấn đề tương tự và giải pháp là phải có chính xác số querychildQuery. Bạn có thể viết lại mã của mình dưới dạng:

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

    next = results.next(); 
} 

nếu đang thực hiện thủ tục khác, bạn phải chuyển nó theo tham chiếu.

7

Thật không may, nó không rõ ràng từ Qt Tài liệu rằng trong trường hợp khi bạn muốn sử dụng QXmlQuery::setFocus(const QXmlItem& item) quá tải để truy vấn các nút con, bạn nên tạo tương ứng QXmlQuery đối tượng sử dụng QXmlQuery(const QXmlNamePool& np) constructor để làm cho họ chia sẻ cùng một đối tượng QXmlNamePool. Chia sẻ như vậy, chỉ cần nói, liên quan đến truy vấn với nhau.

Xét này, ví dụ của bạn sẽ giống như sau:

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

Hơn nữa, bạn có thể đi xa hơn và tái sử dụng ban đầu QXmlQuery đối tượng:

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; 
} 
Các vấn đề liên quan