2009-08-17 19 views
8

Làm cách nào để chạy truy vấn XPath trong QT?Làm cách nào để chạy các truy vấn XPath trong QT?

Tôi cần sắp xếp các thẻ nhất định với các giá trị cụ thể trong một thuộc tính nhất định. Các tài liệu QXmlQuery là bất cứ điều gì nhưng dễ đọc.

Giản đồ tôi đang phân tích cú pháp là định dạng Rhythmbox DB:

 

<rhythmdb version="1.6"> 
    <entry type="ignore"> 
    <title></title> 
    <genre></genre> 
    <artist></artist> 
    <album></album> 
    <location>file:///mnt/disk/music/Cover.jpg</location> 
    <mountpoint>file:///mnt/disk</mountpoint> 
    <mtime>1222396828</mtime> 
    <date>0</date> 
    <mimetype>application/octet-stream</mimetype> 
    <mb-trackid></mb-trackid> 
    <mb-artistid></mb-artistid> 
    <mb-albumid></mb-albumid> 
    <mb-albumartistid></mb-albumartistid> 
    <mb-artistsortname></mb-artistsortname> 
    </entry> 
    <entry type="song"> 
    <title>Bar</title> 
    <genre>Foobared Music</genre> 
    <artist>Foo</artist> 
    <album>The Great big Bar</album> 
    <track-number>1</track-number> 
    <disc-number>1</disc-number> 
    <duration>208</duration> 
    <file-size>8694159</file-size> 
    <location>file:///media/disk/music/01-Foo_-_Bar.ogg 
    <mountpoint>file:///media/disk 
    <mtime>1216995840</mtime> 
    <first-seen>1250478814</first-seen> 
    <last-seen>1250478814</last-seen> 
    <bitrate>301</bitrate> 
    <date>732677</date> 
    <mimetype>application/x-id3</mimetype> 
    <mb-trackid></mb-trackid> 
    <mb-artistid></mb-artistid> 
    <mb-albumid></mb-albumid> 
    <mb-albumartistid></mb-albumartistid> 
    <mb-artistsortname></mb-artistsortname> 
    </entry> 
</rhythmdb> 
 

Đây là Schema XML cơ bản của bạn trong đó có một bộ sưu tập các mục có cấu trúc. Ý định của tôi là lọc ra các mục có loại 'bỏ qua'.

Trả lời

11

Tài liệu liên quan có tại: http://qt-project.org/doc/qt-4.8/qxmlquery.html#running-xpath-expressions.

Giải pháp mà tôi đã đến là sử dụng QXmlQuery để tạo tệp XML rồi phân tích cú pháp lại bằng QDomDocument.

 

RhythmboxTrackModel::RhythmboxTrackModel() 
{ 
    QXmlQuery query; 
    QXmlQuery entries; 
    QString res; 
    QDomDocument rhythmdb; 


    /* 
    * Try and open the Rhythmbox DB. An API call which tells us where 
    * the file is would be nice. 
    */ 
    QFile db(QDir::homePath() + "/.gnome2/rhythmbox/rhythmdb.xml"); 
    if (! db.exists()) { 
     db.setFileName(QDir::homePath() + "/.local/share/rhythmbox/rhythmdb.xml"); 
     if (! db.exists()) 
      return; 
    } 

    if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) 
     return; 

    /* 
    * Use QXmlQuery to execute and XPath query. Check the version to 
    * make sure. 
    */ 
    query.setFocus(&db); 
    query.setQuery("rhythmdb[@version='1.6']/entry[@type='song']"); 
    if (! query.isValid()) 
     return; 

    query.evaluateTo(&res); 
    db.close(); 


    /* 
    * Parse the result as an XML file. These shennanigans actually 
    * reduce the load time from a minute to a matter of seconds. 
    */ 
    rhythmdb.setContent("" + res + ""); 
    m_entryNodes = rhythmdb.elementsByTagName("entry"); 


    for (int i = 0; i < m_entryNodes.count(); i++) { 
     QDomNode n = m_entryNodes.at(i); 
     QString location = n.firstChildElement("location").text(); 

     m_mTracksByLocation[location] = n; 
    } 

    qDebug() << rhythmdb.doctype().name(); 
    qDebug() << "RhythmboxTrackModel: m_entryNodes size is" << m_entryNodes.size(); 
} 
 

Trong trường hợp bất cứ ai đang tự hỏi, đây là mã của tôi lấy từ một nhánh mới của Mixxx project, đặc biệt là chi nhánh features_looping.

Những điều tôi không thích về giải pháp này là:

  • Phân tích XML hai lần
  • Kết nối kết quả với một khởi đầu và kết thúc thẻ.
+0

Bạn không cần phải phân tích cú pháp XML hai lần; chỉ cần sử dụng một quá tải QXmlQuery :: evaluationTo() khác nhau. Chỉ cần sử dụng kết quả 'QXmlResultItems'; query.evaluateTo (& result); ' và sau đó lặp qua 'kết quả' để nhận tất cả các nút phù hợp. Xem http://doc.trolltech.com/main-snapshot/qxmlresultitems.html –

+1

XMLResultItems, XMLItems hoặc XMLNodeItems không đầy đủ như tôi có thể nói từ tài liệu. Như tài liệu nói: "Bởi vì QXmlNodeModelIndex là cố ý một lớp đơn giản, nó không có chức năng thành viên để truy cập các thuộc tính của các nút." –

+0

Như tài liệu nói: "Bởi vì QXmlNodeModelIndex là cố ý một lớp đơn giản, nó không có chức năng thành viên để truy cập các thuộc tính của các nút." Hoàn toàn đồng ý. Có cách nào để chạy một yêu cầu XPath và điều hướng dễ dàng thông qua kết quả không? Tôi bắt đầu nghĩ rằng câu trả lời là không! Tôi đang tìm kiếm trên web trong 2 ngày và tôi không tìm thấy gì cả. Tôi nghĩ rằng tôi sẽ sử dụng Gnome libxml thay vì QtXml, nhưng nó hút bằng cách sử dụng g –

-2

Nếu nó phù hợp với yêu cầu phân tích cú pháp của bạn, bạn có thể sử dụng trình đọc dựa trên SAX thay vì trình đọc dựa trên DOM. Sử dụng QXmlSimpleReader với một QXmlDefaultHandler phân lớp phụ, bạn có thể truy cập vào từng phần tử của truy vấn XPath cũng như các thuộc tính của nó khi tài liệu được quét. Tôi nghĩ rằng cách tiếp cận này sẽ nhanh hơn một phương pháp dựa trên DOM; bạn không phải đọc bất cứ điều gì hai lần và nó đã được xây dựng thành Qt. Có một ví dụ ở đây: http://www.digitalfanatics.org/projects/qt_tutorial/chapter09.html trong phần "Đọc Sử dụng SAX".

+1

Trong khi các trình phân tích cú pháp SAX có vị trí của nó thì không phải vậy. XPath là một công nghệ dựa trên DOM. –

Các vấn đề liên quan