XPath在QT中的使用(QXmlQuery读取XML文件)

7 篇文章 12 订阅
5 篇文章 1 订阅

  最近一段时间和Xml文件算是干上了,先后用了QXmlStream、Dom、Dhtmlxtree、DhtmlXform方式读写Xml文件。昨天接到任务让用Xpath方式实现Xml读取。经过了解在QT中有QxmlQuery类用来实现XPath,接下来就说说这个东东!


1.lib文件:

   要想用QXmlQuery,首先要包含进两个lib文件:QtXmlPatterns4.lib 和 QtXmlPatternsd4.lib

   

2.头文件:

   用的一下这个头文件

#include <QtXmlPatterns/QXmlQuery>


3.xml格式:

   

<?xml version="1.0"?>
<tree id="0">
	<item id="1"  open="1"  text="工作目录" im0="leaf.gif" im1="folderOpen.gif" im2="folderClosed.gif" >
		<item id="11"  select="1" text="工作目录" im0="leaf.gif" im1="folderOpen.gif" im2="folderClosed.gif" >
			<userdata name="value">
				<![CDATA[
           <?xml version="1.0"?>
           <items>
           	 <item type="label" name="label1" label="基本配置"/>
           	 <item type="checkbox" name="check3" checked="true" label="全路径" position="label-right" />
              <item type="radio" name="ffff" checked="" value="online" label="单目录" position="label-right" />
              <item type="radio" name="ffff" checked="true" value="disk"  label="双目录"   position="label-right" />
              <item type="checkbox" name="check1" checked="true" label="前目录" position="label-right"  />
               <item type="checkbox" name="check2" checked="true" label="后目录" position="label-right" />
              <item type="select" name="myselect" label="传递方式" >
               <option text="post" value="op111" selected="" />
               <option text="get" value="op222" selected="true" />
              </item>
              <item type="input" name="inputx" value="2007.7.27更新" label="配置描述"  rows="2" position="label-left" />
           </items>]]>
			</userdata>
		</item>
	</item>
  <item id="2"  open="1"  text="数据服务器地址" im0="leaf.gif" im1="folderOpen.gif" im2="folderClosed.gif" >
  	<item id="21"  text="地址" im0="leaf.gif" im1="folderOpen.gif" im2="folderClosed.gif" >
  		<userdata name="value">
  			<![CDATA[<?xml version="1.0"?>
          <items>
          	 <item type="label" name="label1" label="基本配置"/>
          	 <item type="checkbox" name="check3" checked="true" label="全路径" position="label-right" />
             <item type="radio" name="ffff" checked="" value="online" label="单目录" position="label-right" />
             <item type="radio" name="ffff" checked="true" value="disk"  label="双目录"   position="label-right"  />
          </items>]]>
       </userdata>
  </item>
</tree>

请仔细看我的xml格式,你会发现每一个二级目录下会出现UserDate属性,而内容竟然是个标准的xml文件的语句,之所以这样是项目的需要,这个格式有个好处,如果你对Dhtmlx库了解的话,你会发现:外层的xml格式是DhtmlXTree的标准格式,而内层的xml格式为DhtmlxForm标准格式。明白了吧,实在不明白,上个图吧:



 看懂了吧,左侧是个tree,右侧自动生成form,而且还实现了,对form的写入,具体代码在其他文章中提及了。好了,扯远了。


4.关于QXmlQuery的使用

   QXmlQuery query;
	QString sOptionSettings;
	QDomDocument configxmldoc;
	

    QFile db(sXmlPath);
    if ( ! db.exists()) {
		errMsg = "Xml文件未找到!";
        return errMsg;
    }

	if (!db.open(QIODevice::ReadOnly | QIODevice::Text)){
		errMsg = "文件打不开!";
		return errMsg;
	}
       
    query.setFocus(&db);
   //去和我的xml格式对应一下,很容易就能看出来了。这句就是XPath的标准语法。
   //sFistLabel,sSeconLabel都是参数,都=“工作目录”
    query.setQuery("tree[@id='0']/item[@text='"+sFistLabel+"']/item[@text='"+sSeconLabel+"']/userdata[@name='value']");
	//算是检验查询参数有误
	if ( !query.isValid()){
		errMsg = "查询参数有误!";
		return errMsg;
	}
        
    //把查询出来的语句,赋值给字符串sOptionSettings
    query.evaluateTo(&sOptionSettings);
    db.close();

    //以下三句与我的xml格式有关,要特别注意第一句,这里默认给转行了格式。其实正确的是(见下图)
	 sOptionSettings = sOptionSettings.replace("<","<").replace(">",">").replace("&","&");
	 sOptionSettings = sOptionSettings.replace("<userdata name=\"value\">","");
	 sOptionSettings = sOptionSettings.replace("</userdata>","");
	
	 //此时sOptionSettings是一个完整的xml语句,
   //而且configxmldoc为一个QDomDocument,接下来的事就是Dom解析xml格式
   configxmldoc.setContent(sOptionSettings);


写到这里很多朋友可能会问,既然用Dom方式就能读取Xml,干嘛还用这种方式呢,其实仔细看看我的xml格式,你会发现用QXmlQuery读我的外层xml格式会十分方便,这就是为什么用这个了。

4.目标

  最后说一下,我们这个任务

   我的xml格式如上,当输入(xml目录、一级目录、二级目录、三级目录、返回出错信息),会返回相应的value值。

整个代码如下:

QString PSM_OptionManager::get_config_info(const QString& sXmlPath,
										   const QString& sFistLabel,
										   const QString& sSeconLabel,
										   const QString& sThridLabel, QString& errMsg){

	QXmlQuery query;
	QString sOptionSettings;
	QDomDocument configxmldoc;
	QDomNodeList  sitemNodes;


    QFile db(sXmlPath);
    if ( ! db.exists()) {
		errMsg = "Xml文件未找到!";
        return errMsg;
    }

	if (!db.open(QIODevice::ReadOnly | QIODevice::Text)){
		errMsg = "文件打不开!";
		return errMsg;
	}
       
    query.setFocus(&db);
    query.setQuery("tree[@id='0']/item[@text='"+sFistLabel+"']/item[@text='"+sSeconLabel+"']/userdata[@name='value']");
	
	if ( !query.isValid()){
		errMsg = "查询参数有误!";
		return errMsg;
	}
        

    query.evaluateTo(&sOptionSettings);
	db.close();

	 sOptionSettings = sOptionSettings.replace("<","<").replace(">",">").replace("&","&");
	 sOptionSettings = sOptionSettings.replace("<userdata name=\"value\">","");
	 sOptionSettings = sOptionSettings.replace("</userdata>","");
	
	 //此时sOptionSettings是一个完整的xml语句  

    configxmldoc.setContent(sOptionSettings);
  
    sitemNodes = configxmldoc.elementsByTagName("item");

    for (int i = 0; i < sitemNodes.count(); i++) {
        QDomNode node = sitemNodes.at(i);
		QString itemlabel = node.toElement().attribute("label");
		if (itemlabel == sThridLabel ){
				QString itemtype = node.toElement().attribute("type");
				if(itemtype == "checkbox" || itemtype == "radio") {
					QString itemchecked = node.toElement().attribute("checked");
					if (itemchecked == "true"){
						return "1";
					} 
					else{
						return "0";
					}
				}//end if 

				if (itemtype == "input") {
					QString itemvalue = node.toElement().attribute("value");
					return itemvalue;
				}//end if

				if (itemtype == "select"){
					QDomNodeList  optionlist = node.toElement().childNodes();
					for (int j = 0 ; j < optionlist.count() ; j++) {
						QDomNode optionnode = optionlist.at(j);
						QString optionchecked = optionnode.toElement().attribute("selected");
						if (optionchecked == "true"){
							QString optionvalue = optionnode.toElement().attribute("value");
							return optionvalue;
						}

					}//end for
				}//end if

			}//end if 
		}//end for
        
	return "";
}

调用方式是:

QString sfist = "工作目录";
		QString ssecond = "工作目录";
		QString sthird = "全路径";
		QString sXmlPath = "E:\\settings.xml";


		QString strErrMsg = "";
		get_config_info(sXmlPath,sfist,ssecond,sthird, strErrMsg);

当然,我这是截取了一部分代码,因为我写的QT插件,所以调用代码实在另一个工程里。

好了,就这些吧。

5.资料:

QXmlQuery在线帮助文档


QT菜鸟一只,欢迎批评指正!

   

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值