XSD解析XML

最近项目需求研究XSD,在这里记录下。

首先,完全按照使用手册可以生成xsd对应的hxx和cxx两个文件。按照使用手册上的解析方法就显得很复杂,可将xml文件映射成对应的C++类,然后通过访问函数的方式逐层访问,这势必不方便(有可能才接触,不会其优点)。

后来在网上看到大神在linux下的成功案例。所以依葫芦画瓢在windows下试验了一下,成功。

XMLPlatformUtils::Initialize();
XercesDOMParser* domXmlParser = new XercesDOMParser;


		//配置DOMParser  
		domXmlParser->setValidationScheme(XercesDOMParser::Val_Auto);
		domXmlParser->setDoNamespaces(false);
		domXmlParser->setDoSchema(false);
		domXmlParser->setLoadExternalDTD(false);


		try
		{
			//调用Xerces C++类库提供的解析接口  
			domXmlParser->parse(path.c_str());


			//获得DOM树  
			DOMDocument* xmlDoc = domXmlParser->getDocument();


			DOMElement*	pRoot = xmlDoc->getDocumentElement();
			if (!pRoot)
			{
				throw(std::runtime_error("empty XML document "));
			}


			if (0)
			{
				DOMTreeWalker* walker =
					xmlDoc->createTreeWalker(pRoot, DOMNodeFilter::SHOW_TEXT, NULL, true);


				for (DOMNode *current = walker->nextNode(); current != 0; current = walker->nextNode())
				{
					char   *strValue = XMLString::transcode(current->getNodeValue());
					ui.plainTextEdit->appendPlainText(QString(strValue));
					XMLString::release(&strValue);
				}
			}
			else
			{
				DOMNodeIterator* iterator = xmlDoc->createNodeIterator(pRoot, DOMNodeFilter::SHOW_ELEMENT, NULL, true);


				for (DOMNode* current = iterator->nextNode(); current != 0; current = iterator->nextNode())
				{
					const XMLCh* value = current->getNodeValue();
					const XMLCh* name = current->getNodeName();




					char* strName = XMLString::transcode(current->getNodeName());


					DOMNamedNodeMap* mapAttr = current->getAttributes();


					if (mapAttr)
					{
						for (XMLSize_t index = 0; index < mapAttr->getLength(); index++)
						{
							DOMNode* node = mapAttr->item(index);


							if (node)
							{
								char* strValue1 = XMLString::transcode(node->getNodeValue());
								char* strName1 = XMLString::transcode(node->getNodeName());


								ui.plainTextEdit->appendPlainText(QString::fromLocal8Bit(strName) + ":" + QString::fromLocal8Bit(strName1) + "=" + QString::fromLocal8Bit(strValue1));


								XMLString::release(&strValue1);
								XMLString::release(&strName1);
							}
						}


					}


					XMLString::release(&strName);
				}
			}
		}
		catch (xercesc::XMLException&   excp)
		{
			char*   msg = xercesc::XMLString::transcode(excp.getMessage());
			ostringstream   errBuf;
			errBuf << "Error   parsing   file:   " << msg << flush;
			XMLString::release(&msg);
		}
XMLPlatformUtils::Terminate()。

代码解析:要想利用Xerces   C++类库来解析XML文档,必须要对类库进行初始化,所以在类XML的构造函数中,我们对类库进行了初始化:XMLPlatformUtils::Initialize();

         接下来,我们定义的解析对象,并在构造函数中对其进行了初始化操作,然后,在xmlParser函数中我们调用类库的解析函数接口,传人xml文件名(m_DOMXmlParser->parse(xmlFile.c_str())   ;)。因为在这里我们选用的是DOM方法,所以接下来我们需要创建DOM树:DOMDocument*   xmlDoc  =   m_DOMXmlParser-> getDocument();,并获取DOM树的根节点     DOMElement   *pRoot  =   xmlDoc->getDocumentElement()。

         再接下来是什么呢?根据上面所说的,我们需要遍历这棵DOM树,因此我们需要一种遍历方法,在程序中我给出了两种遍历的方法,一种是创建遍历树   DOMTreeWalker   *walker  =   xmlDoc->createTreeWalker(pRoot,  DOMNodeFilter::SHOW_TEXT,  NULL,   true),还有一种是通过迭代器来遍历整棵DOM树  DOMNodeIterator*   iterator   =  xmlDoc-> createNodeIterator(pRoot,         DOMNodeFilter::SHOW_TEXT,     NULL,  true)。两种方法都可以达到同样的效果。程序中注释掉的代码是创建遍历树方法。

       遍历完,并打印出节点值以后,我们需要终止对类库的调用,所以在析构函数中:XMLPlatformUtils::Terminate()。

       解析简单xml文档的基本步骤就是如此简单,至于复杂的XML文档,解析的步骤,尤其是创建DOM树的方法有点不同,在这里便不作介绍。接下来,来讲一下困扰我多天的中文解析问题。我们知道,Xerces   C++默认只支持节点名中文,至于节点值,属性值则不支持,即使解析出来的也是乱码,所以需要自己解决。在这里,我们选用UTF-8编码格式的XML文档。

XSD专程XML,非常实用。class CSaxContentHandler : public ISAXContentHandler { public: CSaxContentHandler(); virtual ~CSaxContentHandler(); virtual long __stdcall QueryInterface(const struct _GUID &, void **); virtual unsigned long __stdcall AddRef(void); virtual unsigned long __stdcall Release(void); virtual HRESULT STDMETHODCALLTYPE putDocumentLocator( /* [in] */ ISAXLocator __RPC_FAR *pLocator); virtual HRESULT STDMETHODCALLTYPE startDocument(void); virtual HRESULT STDMETHODCALLTYPE endDocument(void); virtual HRESULT STDMETHODCALLTYPE startPrefixMapping( /* [in] */ wchar_t __RPC_FAR *pwchPrefix, /* [in] */ int cchPrefix, /* [in] */ wchar_t __RPC_FAR *pwchUri, /* [in] */ int cchUri); virtual HRESULT STDMETHODCALLTYPE endPrefixMapping( /* [in] */ wchar_t __RPC_FAR *pwchPrefix, /* [in] */ int cchPrefix); virtual HRESULT STDMETHODCALLTYPE startElement( /* [in] */ wchar_t __RPC_FAR *pwchNamespaceUri, /* [in] */ int cchNamespaceUri, /* [in] */ wchar_t __RPC_FAR *pwchLocalName, /* [in] */ int cchLocalName, /* [in] */ wchar_t __RPC_FAR *pwchRawName, /* [in] */ int cchRawName, /* [in] */ ISAXAttributes __RPC_FAR *pAttributes); virtual HRESULT STDMETHODCALLTYPE endElement( /* [in] */ wchar_t __RPC_FAR *pwchNamespaceUri, /* [in] */ int cchNamespaceUri, /* [in] */ wchar_t __RPC_FAR *pwchLocalName, /* [in] */ int cchLocalName, /* [in] */ wchar_t __RPC_FAR *pwchRawName, /* [in] */ int cchRawName); virtual HRESULT STDMETHODCALLTYPE characters( /* [in] */ wchar_t __RPC_FAR *pwchChars, /* [in] */ int cchChars); virtual HRESULT STDMETHODCALLTYPE ignorableWhitespace( /* [in] */ wchar_t __RPC_FAR *pwchChars, /* [in] */ int cchChars); virtual HRESU
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值