QtXML DOM解析/ iTunes库

时间:2013-07-23 15:54:19

标签: c++ qt itunes qtxml

我正在尝试通过解析XML库(iTunes目录中的iTunes Music Library.xml)来获取iTunes专辑列表。

#include <iostream>
#include <QtCore>
#include <QFile>
#include <QtXml>

using namespace std;

void parse(QDomNode n) {

    while(!n.isNull()) {

        // If the node has children
        if(n.hasChildNodes() && !n.isNull()) {

            // We get the children
            QDomNodeList nChildren = n.childNodes();

            // We print the current tag name
            //std::cout << "[~] Current tag : <" << qPrintable(n.toElement().tagName()) << ">" << std::endl;

            // And for each sub-tag of the current tag
            for(int i = 0; i < nChildren.count(); i++) {

                // We get the children node
                QDomNode nChild = nChildren.at(i);
                // And the tag value (we're looking for *Album* here)
                QString tagValue = nChild.toElement().text();

                // If the tag isn't null and contain *Album*
                if(!nChild.isNull() && tagValue == "Album") {
                    // The album name is in the next tag
                    QDomElement albumNode = nChild.nextSiblingElement();
                    std::cout << "[-] Album found -> " << qPrintable(albumNode.text()) << std::endl;
                }

                // And we parse the children node
                parse(nChild);
            }
        }

        n = n.nextSibling();
    }
}

int main() {

    QDomDocument doc("Lib");
    QFile file("/Users/wizardman/QtRFIDMusic/Lib.min.xml");
    if(!file.open(QIODevice::ReadOnly))
        return 1;
    if(!doc.setContent(&file)) {
        file.close();
        return 1;
    }
    file.close();

    // Root element
    QDomElement docElem = doc.documentElement();

    // <plist> -> <dict>
    QDomNode n = docElem.firstChild().firstChild();

    cout << endl << "Album list" << endl;
    cout << "------------------------------------" << endl;


    parse(n);

    return 0;
}

iTunes的XML不是真正的标准XML,相册的名称存储在每个条目的<key>Album</key>旁边的节点中。 Here is what it looks like。我故意将一些节点重命名为调试目的(看看我是否在输出中找到它们)。

这是我的输出:

Album list
------------------------------------
[-] Album found -> J Dilla - Legacy Vol.1
[-] Album found -> J Dilla - Legacy Vol.2
[-] Album found -> J Dilla - Legacy Vol.1
[-] Album found -> J Dilla - Legacy Vol.2
[-] Album found -> J Dilla - Legacy Vol.2
[-] Album found -> J Dilla - Legacy Vol.2

我无法理解为什么循环正在重新分析第一个节点。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

在我的调试器下运行代码之后......看起来你在子代中迭代了太多次。意思是,你递归遍历整个树(重复)在&lt; dict&gt;,内部&lt; dict&gt;,&lt; dict_FOCUS&gt;还有&lt; dict_FOCUS2&gt;。

对我来说,使用QDomNode :: firstChildElement(QString)通过节点迭代(不递归)更容易; 我无法保证这是防弹......但这是一个开始! ;)

// Root element
QDomElement docElem = doc.documentElement();

// <plist> -> <dict>
QDomNode n = docElem.firstChildElement().firstChildElement("dict");

qDebug() << "Album list";
qDebug() << "------------------------------------";

QDomNodeList list = n.childNodes();
int count = list.count();

for(int i = 0; i < count; ++i)
{
  QDomElement node = list.at(i).toElement();
  if(node.tagName().startsWith("dict_FOCUS"))
  {
    node = node.firstChildElement();
    while(!node.isNull())
    {
      if(node.text() == "Album" && node.tagName() == "key")
      {
        node = node.nextSiblingElement();
        if(!node.isNull() && node.tagName() == "string")
        {
          qDebug() << "[-] Album found -> " << qPrintable(node.text());
        }
      }
      node = node.nextSiblingElement();
    }
  }
}