Разбор QtXML DOM / Библиотека iTunes

Я пытаюсь получить список альбомов iTunes, анализируя библиотеку XML (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;
}

XML в iTunes на самом деле не является стандартным XML, название альбома хранится в узле рядом с <key>Album</key> для каждой записи. Вот как это выглядит. Я намеренно переименовал некоторые узлы в целях отладки (чтобы увидеть, достигну ли я их в своем выводе).

И вот мой вывод:

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

Я не могу понять, почему цикл повторяет первые узлы. Есть идеи ?

0

Решение

После запуска вашего кода под моим отладчиком … кажется, что вы перебираете дочерние элементы слишком много раз. Это означает, что вы рекурсивно проходите по всему дереву (неоднократно) в <ДИКТ>, внутренний <ДИКТ>, <dict_FOCUS> а также <dict_FOCUS2>,

Для меня было проще просто итерировать (без рекурсии) по узлам, используя 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();
}
}
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]