PDA

View Full Version : Problems reading XML with QDomDocument



grantbj74
26th August 2009, 06:00
Hi,

I am trying to read configuration with QDomDocument. I managed to get writting configuration to work. When reading I get the settings but don't get any phone numbers.

This is an example of what I might read (there can be between 0 and 999 phone numbers):



<!--Main Settings-->
<settings AfterHourOffset="100" NumPerButton="1" MaxNumToDial="1" />
<!--Phone Book List-->
<phone location="0" value="911" />
<phone location="1" value="33782134" />
<phone location="2" value="000" />
<phone location="3" value="ABCD" />
<phone location="8" value="13005696" />
<phone location="990" value="38441104" />
<phone location="999" value="131333" />


Here's my current attempt:



QFile file("fred.xml");

if(file.open(QIODevice::ReadOnly | QIODevice::Text)) {

QDomDocument d;

d.setContent(&file);

QDomNode n = d.firstChild();

ClearPhoneNumbers(); // Clear phone table.

while(!n.isNull()) {

if(n.isElement()) {

QDomElement e = n.toElement();
QString name = e.tagName();

if(name == "settings") {

ui->Edit1->setText(e.attribute("AfterHourOffset",""));
ui->Edit2->setText(e.attribute("MaxNumToDial",""));
ui->Edit3->setText(e.attribute("NumPerButton",""));

} else if(name == "phone") {

QString location = e.attribute("location","");
QString value = e.attribute("value","");

AddPhoneBook(location, value); // Add to phone table.
}
}
n = n.nextSibling();
}
file.close();
}


See whats wrong? :confused:

Thanks
Brendan

spirit
26th August 2009, 06:29
your xml format is not corrected. (you xml doesn't contain root element).
you should have xml like this


<phones>
<!--Main Settings-->
<settings AfterHourOffset="100" NumPerButton="1" MaxNumToDial="1" />
<!--Phone Book List-->
<phone location="0" value="911" />
<phone location="1" value="33782134" />
<phone location="2" value="000" />
<phone location="3" value="ABCD" />
<phone location="8" value="13005696" />
<phone location="990" value="38441104" />
<phone location="999" value="131333" />
</phones>

kwisp
26th August 2009, 06:40
I think you should use something as:


<?xml version='1.0' encoding='windows-1251'?>
<root>
<data1></data1>
....
</root>

grantbj74
26th August 2009, 07:22
Thanks for replies,

I tried both suggestions. Now it only collects the root element. Then after NextSibling is called it breaks out of the while loop. So nothing is collected. I must be missing something.

kwisp
26th August 2009, 07:33
I use this code to read xml.


bool CSKHttp::GetDataFromXml(CSKRequest* req)
{
QDomDocument domDoc;
QString errorString;
int errorLine;
int errorColumn;
req->m_buffer.open(QIODevice::ReadOnly);
QByteArray byteArray(req->m_buffer.readAll());
req->m_buffer.close();
if(!(domDoc.setContent(byteArray,false,&errorString,&errorLine,&errorColumn))) {
mocW("rq")<<"xml document error <MESS:"<<errorString<<"><LINE"
<<errorLine<<"><COLUMN"<<errorColumn<<">"<<endl;
mocW("rq")<<"<ANSWER:"<<byteArray<<">"<<endl;
return false;
}
QDomElement domElement = domDoc.documentElement();
byteArray.replace("\n"," ");
mocD("rq")<<"<ANSWER:"<<byteArray<<">"<<endl;
TraverseXmlNode(domElement,req);
return true;
}

void CSKHttp::TraverseXmlNode(const QDomNode& node, CSKRequest* req)
{
QDomNode domNode = node.firstChild();
QDomElement domElement;
while(!(domNode.isNull())) {
if(domNode.isElement()) {
domElement = domNode.toElement();
if(!(domElement.isNull()))
req->Data(domElement.tagName(),domElement.text());
}
TraverseXmlNode(domNode,req);
domNode = domNode.nextSibling();
}
}

may be useful for you.

victor.fernandez
26th August 2009, 07:38
You get the first child, which would be "phones". Then you try to get its siblings but it doesn't have any. You need to get the children of phones. So you can do:


QDomDocument d;
d.setContent(&file);

QDomNode n = d.firstChild();
if(!n.isNull() || !n.hasChildNodes())
return;

n = n.firstChild();

ClearPhoneNumbers(); // Clear phone table.

while(!n.isNull()) {
...

spirit
26th August 2009, 07:38
I wrote this in a browser, but I'm sure that this code works fine. ;)


QDomDocument doc;
QFile file("phones.xml");
if (!file.open(QIODevice::ReadOnly))
return;
if (!doc.setContent(&file)) {
file.close();
return;
}
file.close();

QDomElement docElem = doc.documentElement();

QDomNode n = docElem.firstChild();
while(!n.isNull()) {
QDomElement e = n.toElement();
if(!e.isNull()) {
if (e.tagName() == "phone") {
qDebug() << "location" << e.attribute("location");
qDebug() << "value" << e.attribute("value");
} else if (e.tagName() == "settings") {
qDebug() << "AfterHourOffset" << e.attribute("AfterHourOffset");
qDebug() << "NumPerButton" << e.attribute("NumPerButton");
qDebug() << "MaxNumToDial" << e.attribute("MaxNumToDial");
}
}
n = n.nextSibling();
}

grantbj74
27th August 2009, 01:00
Thanks poeple. ;)

Spirits version worked for me.

I ended up making mine a combination of Spirit and victor.fernandez ideas.

I'm a bit scared to do recursive programming unless its required.

kwisp
27th August 2009, 06:47
Thanks poeple. ;)
....
I'm a bit scared to do recursive programming unless its required.

don`t be afraid it`s realy easy.

victor.fernandez
27th August 2009, 08:14
I'm a bit scared to do recursive programming unless its required.

There is some risk of making a mistake and entering an infinite recursion but no more than there is with a plain for(). Being a bit careful, you should not be afraid of it. Also keep in mind that by traversing a QDomDocument you won't have any problem because it's a plain tree without loop backs.