2009-08-17 4 views
8

Как запустить запрос XPath в QT?Как запустить запросы XPath в QT?

Мне нужно отсортировать определенные теги с определенными значениями в определенном атрибуте. Документация QXmlQuery ничем не отличается.

Схема Я разбора формат 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> 
 

Это ваш основной XML-схемы, которая имеет набор структурированных записей. Мое намерение состояло в том, чтобы отфильтровать записи с типом «игнорировать».

ответ

11

Соответствующая документация находится по адресу: http://qt-project.org/doc/qt-4.8/qxmlquery.html#running-xpath-expressions.

Решение, к которому я пришел, состояло в том, чтобы использовать QXmlQuery для генерации XML-файла, а затем снова проанализировать его с помощью 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(); 
} 
 

В случае, если кто-то интересно, это мой код взят из последней ветви Mixxx project, в частности features_looping филиал.

Вещи, которые я не люблю об этом растворе:

  • Разбор XML дважды
  • Конкатенации результата с начальным и конечной меткой.
+0

Вам не нужно анализировать XML дважды; просто используйте другую перегрузку QXmlQuery :: valuTo(). Просто используйте результат QXmlResultItems; query.evaluateTo (& result); ' а затем перебираем «результат», чтобы получить все соответствующие узлы. См. Http://doc.trolltech.com/main-snapshot/qxmlresultitems.html –

+1

XMLResultItems, XMLItems или XMLNodeItems не являются достаточными, насколько я могу судить по документации. Как говорится в документации: «Поскольку QXmlNodeModelIndex преднамеренно является простым классом, у него нет функций-членов для доступа к свойствам узлов». –

+0

Как говорится в документации: «Поскольку QXmlNodeModelIndex преднамеренно представляет собой простой класс, он не имеет функций-членов для доступа к свойствам узлов». Полностью согласен. Есть ли ПРОСТОЙ способ запускать запрос XPath и легко перемещаться по результату? Я начинаю думать, что ответ - нет! Я ищу в Интернете 2 дня, и я ничего не нахожу. Я думаю, что я собираюсь использовать Gnome libxml вместо QtXml, но это отстой, используя g – 2011-03-03 10:19:16

-2

Если это соответствует вашим требованиям синтаксического анализа, вы можете использовать считыватель на основе SAX вместо DOM-based. Используя QXmlSimpleReader с подклассифицированным QXmlDefaultHandler, вы можете получить доступ к каждому элементу вашего запроса XPath, а также к его атрибутам при проверке документа. Я думаю, что этот подход будет быстрее, чем DOM-based; вам не нужно ничего читать дважды, и он уже встроен в Qt. Здесь приведен пример: http://www.digitalfanatics.org/projects/qt_tutorial/chapter09.html в разделе «Чтение с использованием SAX».

+1

Хотя SAX-парсеры имеют свое место, это не так. XPath - это технология, основанная на DOM. –

Смежные вопросы