QT自带例子:
C:\Qt\Qt5.5.1\Examples\Qt-5.5\widgets\itemviews\simpledommodel\simpledommodel.pro
C:\Qt\Qt5.5.1\Examples\Qt-5.5\xml\dombookmarks\dombookmarks.pro
http://blog.sina.com.cn/s/blog_a6fb6cc90101eupl.html
如何使用QXmlStreamReader来解析格式良好的XML,Qt的文档中指出,它是一种更快、更方便的Qt自己的SAX解析器(QXmlSimpleReader)的替代,它也较快,在某种情况下,比DOM(QDomDocument)更方便。
下面是对 QXmlStreamReader 读取XML格式的原理探讨图,下面是对 以<和>为分界线对XML进行解析(除了刚开始的注释外)
<?xml version="1.0" encoding="UTF-8"?>
<persons name="Qt">
<person id="1">
<name>wang</name>
<age>24</age>
<email>wang@sina.com</email>
<website>www.wang.com</website>
</person>
<person id="2">
<name>sugon</name>
<age>25</age>
<email>sugon@sina.com</email>
<website>www.sugon.com</website>
</person>
</persons>
Starting E:\delcode\build-untitled-Desktop_Qt_5_5_1_MSVC2010_32bit-Debug\debug\untitled.exe...
[wificommon]开始进入....readNext before: 1 0
readNext after: 1 38 "StartDocument"
readNext before: 1 38
readNext after: 2 19 "StartElement"
readNext before: 2 19
readNext after: 3 1 "Characters"
readNext before: 3 1
readNext after: 3 15 "StartElement"
readNext before: 3 15
readNext after: 4 1 "Characters"
readNext before: 4 1
readNext after: 4 6 "StartElement"
readNext before: 4 6
readNext after: 4 11 "Characters"
readNext before: 4 11
readNext after: 4 17 "EndElement"
readNext before: 4 17
readNext after: 5 1 "Characters"
readNext before: 5 1
readNext after: 5 5 "StartElement"
readNext before: 5 5
readNext after: 5 8 "Characters"
readNext before: 5 8
readNext after: 5 13 "EndElement"
readNext before: 5 13
readNext after: 6 1 "Characters"
readNext before: 6 1
readNext after: 6 7 "StartElement"
readNext before: 6 7
readNext after: 6 21 "Characters"
readNext before: 6 21
readNext after: 6 28 "EndElement"
readNext before: 6 28
readNext after: 7 1 "Characters"
readNext before: 7 1
readNext after: 7 9 "StartElement"
readNext before: 7 9
readNext after: 7 22 "Characters"
readNext before: 7 22
readNext after: 7 31 "EndElement"
readNext before: 7 31
readNext after: 8 1 "Characters"
readNext before: 8 1
readNext after: 8 9 "EndElement"
readNext before: 8 9
readNext after: 9 1 "Characters"
readNext before: 9 1
readNext after: 9 15 "StartElement"
readNext before: 9 15
readNext after: 10 1 "Characters"
readNext before: 10 1
readNext after: 10 6 "StartElement"
readNext before: 10 6
readNext after: 10 12 "Characters"
readNext before: 10 12
readNext after: 10 18 "EndElement"
readNext before: 10 18
readNext after: 11 1 "Characters"
readNext before: 11 1
readNext after: 11 5 "StartElement"
readNext before: 11 5
readNext after: 11 8 "Characters"
readNext before: 11 8
readNext after: 11 13 "EndElement"
readNext before: 11 13
readNext after: 12 1 "Characters"
readNext before: 12 1
readNext after: 12 7 "StartElement"
readNext before: 12 7
readNext after: 12 22 "Characters"
readNext before: 12 22
readNext after: 12 29 "EndElement"
readNext before: 12 29
readNext after: 13 1 "Characters"
readNext before: 13 1
readNext after: 13 9 "StartElement"
readNext before: 13 9
readNext after: 13 23 "Characters"
readNext before: 13 23
readNext after: 13 32 "EndElement"
readNext before: 13 32
readNext after: 14 1 "Characters"
readNext before: 14 1
readNext after: 14 9 "EndElement"
readNext before: 14 9
readNext after: 15 1 "Characters"
readNext before: 15 1
readNext after: 15 10 "EndElement"
readNext before: 15 10
readNext after: 16 0 "EndDocument"
代码如下:
void MainWindow::parseXML(QString file_name)
{
/*if(file_name.isEmpty())
return;
QFile *file = new QFile(file_name);
if(!file->open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::information(NULL, QString("title"), QString("open error!"));
return;
}
//QXmlStreamReader操作任何QIODevice.
QXmlStreamReader xml(file);
QList<QMap<QString,QString> > persons;
//解析XML,直到结束
while(!xml.atEnd() && !xml.hasError())
{
//读取下一个element.
qDebug()<<"readNext before:"<<xml.lineNumber()<<xml.columnNumber();
QXmlStreamReader::TokenType token = xml.readNext();// <?xml version="1.0" encoding="UTF-8"?
qDebug()<<"readNext after:"<<xml.lineNumber()<<xml.columnNumber()<<xml.tokenString();
}
if(xml.hasError())
{
QMessageBox::information(NULL, QString("parseXML"), xml.errorString());
}
//从reader中删除所有设备、数据,并将其重置为初始状态
xml.clear();
*/
#if 1
if(file_name.isEmpty())
return;
QFile *file = new QFile(file_name);
if(!file->open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::information(NULL, QString("title"), QString("open error!"));
return;
}
//QXmlStreamReader操作任何QIODevice.
QXmlStreamReader xml(file);
QList<QMap<QString,QString> > persons;
//解析XML,直到结束
while(!xml.atEnd() && !xml.hasError())
{
//读取下一个element.
//qDebug()<<xml.lineNumber()<<xml.columnNumber()<<xml.characterOffset();
QXmlStreamReader::TokenType token = xml.readNext();// <?xml version="1.0" encoding="UTF-8"?
//qDebug()<<xml.lineNumber()<<xml.columnNumber()<<xml.characterOffset();
//如果获取的仅为StartDocument,则进行下一个 //! QXmlStreamReader::StartDocument == <?xml version="1.0" encoding="UTF-8"?>
if(token == QXmlStreamReader::StartDocument)
{
//qDebug()<<"xml.documentVersion.toString()"<<xml.documentVersion().toString();
//qDebug()<<"xml.documentEncoding.toString()"<<xml.documentEncoding().toString();
continue;
}
//如果获取了StartElement,则尝试读取
if(token == QXmlStreamReader::StartElement)
{
//如果为persons,直接进入下一个
if(xml.name() == "persons" && xml.attributes().hasAttribute("name") ==true)
{
qDebug()<<xml.attributes().value("name").toString();
continue;
}
//如果为person,则对其进行解析
if(xml.name() == "person")
{
persons.append(this->parsePerson(xml));
}
}
}
qDebug()<<"persons="<<persons;
if(xml.hasError())
{
QMessageBox::information(NULL, QString("parseXML"), xml.errorString());
}
//从reader中删除所有设备、数据,并将其重置为初始状态
xml.clear();
#endif
}
QMap<QString,QString> MainWindow::parsePerson(QXmlStreamReader& xml)
{
QMap<QString,QString> person;
//检查是否获取person
//qDebug()<<"xml.name()="<<xml.name()<<xml.tokenType();
if(xml.tokenType() != QXmlStreamReader::StartElement &&
xml.name() == "person")
{
return person;
}
//获取person属性
QXmlStreamAttributes attributes = xml.attributes();
if(attributes.hasAttribute("id"))
{
person["id"] = attributes.value("id").toString();
}
//操作下一个
xml.readNext();
//qDebug()<<"readNext xml.name()="<<xml.name()<<xml.tokenType();
while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
xml.name() == "person"))
{
if(xml.tokenType() == QXmlStreamReader::StartElement)
{
if(xml.name() == "name")
{
this->addElementDataToMap(xml, person);
}
if(xml.name() == "age")
{
this->addElementDataToMap(xml, person);
}
if(xml.name() == "email")
{
this->addElementDataToMap(xml, person);
}
if(xml.name() == "website")
{
this->addElementDataToMap(xml, person);
}
}
xml.readNext();
}
QString id = person["id"];
QString name = person["name"];
QString age = person["age"];
QString email = person["email"];
QString website = person["website"];
return person;
}
void MainWindow::addElementDataToMap(QXmlStreamReader& xml,
QMap<QString, QString>& map) const
{
if(xml.tokenType() != QXmlStreamReader::StartElement)
{
return;
}
QString elementName = xml.name().toString();
xml.readNext();
if(xml.tokenType() != QXmlStreamReader::Characters)
{
return;
}
map.insert(elementName, xml.text().toString());
}
void MainWindow::on_tx_clicked()
{
//QFile file("C:\Users\Administrator\Desktop\image\\test.xml");
parseXML("C:\\Users\\Administrator\\Desktop\\image\\test.xml");
// file.open(QFile::ReadOnly | QFile::Text);
// xml.setDevice(&file);
// int icnt = 0;
}
void MainWindow::on_tx_clicked()
{
//QFile file("C:\Users\Administrator\Desktop\image\\test.xml");
//parseXML("C:\\Users\\Administrator\\Desktop\\image\\test.xml");
// file.open(QFile::ReadOnly | QFile::Text);
// xml.setDevice(&file);
// int icnt = 0;
QFile file("C:\\Users\\Administrator\\Desktop\\image\\test1.xml");
file.open(QFile::WriteOnly | QFile::Text);
writeFile(&file);
}
//! [1]
bool MainWindow::writeFile(QIODevice *device)
{
wxml.setAutoFormatting(true);
wxml.setDevice(device);
wxml.writeStartDocument();
wxml.writeDTD("<!DOCTYPE xbel>");//! xml 的解析方式为 xbel
wxml.writeStartElement("xx");
wxml.writeAttribute("folded", "yes" );
wxml.writeTextElement("title", "12345");
wxml.writeEmptyElement("hello");
wxml.writeEndElement();
wxml.writeEndDocument();
return true;
}
效果如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xbel>
<xx folded="yes">
<title>12345</title>
<hello/>
</xx>
写也可以通过流的方式,更加简单,如下所示:
class XmlStreamLint
{
public:
Q_DECLARE_TR_FUNCTIONS(XmlStreamLint)
};
int main(int argc, char *argv[])
{
enum ExitCode
{
Success,
ParseFailure,
ArgumentError,
WriteError,
FileFailure
};
QCoreApplication app(argc, argv);
QTextStream errorStream(stderr);
if (argc != 2)
{
errorStream << XmlStreamLint::tr(
"Usage: xmlstreamlint <path to XML file>\n");
return ArgumentError;
}
QString inputFilePath(QCoreApplication::arguments().at(1));
QFile inputFile(inputFilePath);
if (!QFile::exists(inputFilePath))
{
errorStream << XmlStreamLint::tr(
"File %1 does not exist.\n").arg(inputFilePath);
return FileFailure;
} else if (!inputFile.open(QIODevice::ReadOnly)) {
errorStream << XmlStreamLint::tr(
"Failed to open file %1.\n").arg(inputFilePath);
return FileFailure;
}
QFile outputFile("C:\\Users\\Administrator\\Desktop\\image\\test2.xml");
if (!outputFile.open( QIODevice::WriteOnly))
{
errorStream << XmlStreamLint::tr("Failed to open stdout.");
return WriteError;
}
// QFile outputFile;
// if (!outputFile.open(stdout, QIODevice::WriteOnly))
// {
// errorStream << XmlStreamLint::tr("Failed to open stdout.");
// return WriteError;
// }
//! [0]
QXmlStreamReader reader(&inputFile);
QXmlStreamWriter writer(&outputFile);
//! [0]
//! [1]
while (!reader.atEnd())
{
reader.readNext();
if (reader.error())
{
errorStream << XmlStreamLint::tr(
"Error: %1 in file %2 at line %3, column %4.\n").arg(
reader.errorString(), inputFilePath,
QString::number(reader.lineNumber()),
QString::number(reader.columnNumber()));
return ParseFailure;
//! [1]
//! [2]
} else
writer.writeCurrentToken(reader);
}
//! [2]
return Success;
}
readXmlFile(m_initFolderPath+"/"+m_xmlFileName);void MainWindow::readXmlFile(QString fileName)
{
QFile file(fileName);
if(!file.open(QFile::ReadOnly | QFile::Text))
{
qDebug()<<"open file"<<fileName<<"failed, error:"<<file.errorString();
return;
}
QDomDocument document;
QString strError;
int errLin = 0, errCol = 0;
if( !document.setContent(&file, false, &strError, &errLin, &errCol) )
{
qDebug()<<"parse file failed at line"<<errLin<<",column"<<errCol<<","<<strError;
return;
}
if( document.isNull() )
{
qDebug()<<"document is null !";
return;
}
QDomElement root = document.documentElement();
qDebug()<<root.tagName();
QDomElement catalogs = root.firstChildElement();
if( catalogs.isNull() )
{
return;
}
else
{
//qDebug()<<catalogs.tagName();
}
while(!catalogs.isNull())
{
foreachElement(catalogs);
catalogs = catalogs.nextSiblingElement();
}
file.close();
}
void MainWindow::foreachElement(QDomElement catalogs)
{
if(catalogs.tagName()=="")
return;
//qDebug()<<catalogs.tagName();
if(catalogs.hasAttributes())
{
QDomNamedNodeMap map = catalogs.attributes();
if(catalogs.tagName()==NodeSystemButton)
{
createSystemButton(map);
}
else if(catalogs.tagName()==NodeSAction)
{
createSAction(map);
}
else if(catalogs.tagName()==NodeRibbonPageSystemPopup)
{
createRibbonPageSystemPopup(map);
}
else if(catalogs.tagName()==NodeSRAction)
{
createSRAction(map);
}
else if(catalogs.tagName()==NodeRibbonQuickAccessBar)
{
createQuickAccessBar(map);
}
else if(catalogs.tagName()==NodeExitsAction)
{
bindingExitsAction(map);
}
else if(catalogs.tagName()==NodeQuickAction)
{
createQuickAction(map);
}
else if(catalogs.tagName()==NodeRibbonPage)
{
createRibbonPage(map);
}
else if(catalogs.tagName()==NodeRibbonGroup)
{
createRibbonGroup(map);
}
else if(catalogs.tagName()==NodeOptionButtonAction)
{
}
else if(catalogs.tagName()==NodeQMenu)
{
createPMenu(map);
}
else if(catalogs.tagName()==NodeQAction)
{
createPMQAction(map);
}
else if(catalogs.tagName()==NodePageQAction)
{
createPageQAction(map);
}
else if(catalogs.tagName()==NodeRibbonStatusBar)
{
createRibbonStatusBar();
}
else if(catalogs.tagName()==NodeStatusAction)
{
createStatusAction(map);
}
}
if(catalogs.hasChildNodes())
{
for(int i=0;i<catalogs.childNodes().length();++i)
{
foreachElement(catalogs.childNodes().at(i).toElement());
}
}
}
QString MainWindow::getNodeValue(QDomNamedNodeMap map, QString key)
{
QString tempValue=map.namedItem(key).nodeValue();
if(key=="Icon")
tempValue=m_initFolderPath+"/"+m_imageFolder+"/"+tempValue;
return tempValue;
}
<?xml version="1.0" encoding="gb2312"?>
<xxx>
<!--0不显示此列 -->
<rrr>ttx1</rrr>
<tx test33="abc" test22="efg">1</tx>
</xxx>
QStringList MainWindow::SMSDXmlGet(QDomNodeList &value)
{
int cnt = value.count();
for(int i=0;i<cnt;i++)
{
QDomNode childNode=value.at(i);
QDomNode::NodeType ttype = childNode.nodeType();
QString nodeName = childNode.nodeName();
QString nodeValue= childNode.nodeValue();
QDomElement elem = childNode.toElement();
//elem.text();
qDebug() << "i==:" << i << "nodeName:" << nodeName << "nodeValue:" << nodeValue<< "NodeType:" << ttype<< "elem:" << elem.text();
}
QStringList ret;
return ret;
}
QStringList MainWindow::SMSDXmlGet(QDomNodeList &value)
{
int cnt = value.count();
for(int i=0;i<cnt;i++)
{
QDomNode childNode=value.at(i);
QDomNode::NodeType ttype = childNode.nodeType();
QString nodeName = childNode.nodeName();
QString nodeValue= childNode.nodeValue();
QDomNamedNodeMap attributeMap = childNode.attributes();
QDomNode attribute = attributeMap.item(0);
QString s1= attribute.nodeName();
QString s2= attribute.nodeValue();
int tt;
}
QStringList ret;
return ret;
}
void MainWindow::pushButton_4Slot()
{
int i=0;
QString filePath="mytest.xml";
QFile file(filePath);
if (file.open(QIODevice::ReadOnly))
{
QDomDocument document;
if (document.setContent(&file))
{
QDomNode &RootDomNode = document;
int RootDomNodeChildsCnt = RootDomNode.childNodes().count();
for(int i=1;i<RootDomNodeChildsCnt;i++)
{
QDomNode childNode = RootDomNode.childNodes().item(i);
QDomElement ele = RootDomNode.firstChildElement("ServiceManageShowDlgSet");
QDomNode ttx = RootDomNode.namedItem("serviceCNName") ;
QString sttx = ttx.nodeValue();
QDomNodeList childList = ele.childNodes();
int cnt=childList.count();
QStringList sRet= SMSDXmlGet(childList);
int tt=99;
// int childListCnt = childList.count();
// QString nodeName = childNode.nodeName();
// QString nodeValue= childNode.nodeValue();
// QDomNamedNodeMap attributeMap = childNode.attributes();
// QDomNode attribute = attributeMap.item(i);
// QString s1= attribute.nodeName();
// QString s2= attribute.nodeValue();
}
}
file.close();
}
}
创建XML:
int main( int argc, char **argv )
{
QApplication a( argc, argv );
QDomDocument doc("MyML");
QDomElement root = doc.createElement("MyML");
doc.appendChild(root);
QDomElement tag = doc.createElement("Greeting");
root.appendChild(tag);
QDomText t = doc.createTextNode("Hello World");
tag.appendChild(t);
QString xml = doc.toString();
//qDebug()<<"xml"<<xml;
QFile file("mydocument.xml"); //! 如果没有此XML,会自动创建,如果有此XML,会覆盖此XML
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate |QIODevice::Text))
return 0;
QTextStream out(&file);
out.setCodec("UTF-8");
doc.save(out,4,QDomNode::EncodingFromTextStream);
file.close();
return 0;
}