Xerces是一个完全符合W3C的DOM标准的项目。它完全提供了W3C的DOM标准规定的接口。
在Java的JDK中提供的也是一个W3C的DOM标准接口。
Xerces是一个完全符合W3C的DOM标准的项目。它完全提供了W3C的DOM标准规定的接口。
在Java的JDK中提供的也是一个W3C的DOM标准接口。有理由相信,JDK提供的W3C的DOM实现就是Xerces的java版本!
在java中,我一般使用的dom4j或者jdom来处理xml文件。这些库提供了比W3C的DOM标准更加方便的类库。
因此,今天,当我使用Xerces的C++版本处理xml文件时遇到了问题。
突出的问题就是,W3C标准中,文本也属于一个节点,即使全部是空格。
这样,当我们使用W3C标准的Element得到它的所有子节点时,就多出了很多我们不需要的空白的Text节点!
当我们使用W3C标准处理XML文件时,这需要特别注意!
下面是使用Xerces C++读取一个xml文件的标签和内容的程序。
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
////////////////xml
#include <xercesc/dom/DOM.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
//包括了所有<xercesc/dom/下的头文件
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#pragma comment( lib, "..\\debug\\xerces-c_2_8D.lib" )
//#pragma comment( lib, "..\\debug\\xerces-c_static_2D.lib" )
//#pragma comment( lib, "..\\debug\\xerces-depdom_2D.lib" )
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
using namespace XERCES_CPP_NAMESPACE;
try {
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch) {
char* message = XMLString::transcode(toCatch.getMessage());
cout << "Error during initialization! :\n"
<< message << "\n";
XMLString::release(&message);
return 1;
}
XercesDOMParser* parser = new XercesDOMParser();
parser->setValidationScheme(XercesDOMParser::Val_Always);
parser->setDoNamespaces(true); // optional
ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
parser->setErrorHandler(errHandler);
char* xmlFile = "x1.xml";
DOMDocument *doc = 0;
try {
parser->parse(xmlFile);
doc=parser->getDocument();
DOMElement * root=doc->getDocumentElement();
cout<<XMLString::transcode(root->getTagName())<<endl;
DOMNodeList* pDOMNodeList=root->getChildNodes();
DOMNode* pTmp=0;
for(XMLSize_t i=0;i<pDOMNodeList->getLength();i++){
pTmp=pDOMNodeList->item(i);
if(pTmp->getNodeType()==DOMNode::ELEMENT_NODE){
DOMElement* pDOMElement =(DOMElement*)pTmp;
std::cout <<XMLString::transcode(pTmp->getNodeName())<<"="<<XMLString::transcode(pDOMElement->getTextContent())<<endl;
}
}
}
catch (const XMLException& toCatch) {
char* message = XMLString::transcode(toCatch.getMessage());
cout << "Exception message is: \n"
<< message << "\n";
XMLString::release(&message);
return -1;
}
catch (const DOMException& toCatch) {
char* message = XMLString::transcode(toCatch.msg);
cout << "Exception message is: \n"
<< message << "\n";
XMLString::release(&message);
return -1;
}
catch (...) {
cout << "Unexpected Exception \n" ;
return -1;
}
delete parser;
delete errHandler;
int i0=0;
cin>>i0;
return 0;
}
得到元素的所有子节点时,大概会把所有的空格等作为一个DOMText文本节点来处理!
所有真正的子节点,会作为DOMElement类型返回。我们只需要处理它即可。
DOMNode* 接口的只有DOMText的getNodeValue()返回的是文本,其他DOMNode的子类型都是返回NULL。
因此,我不得不转换为DOMElement*,使用它的getTextContent()方法得到内容。
另外,提供Java版本的W3C标准的DOM实现来处理xml文件的代码:
File f = new File("D:\\vsProject\\workspace\\TestA\\TestA\\x1.xml");
DocumentBuilderFactory factory
= DocumentBuilderFactory.newInstance();
DocumentBuilder builder
= factory.newDocumentBuilder();
Document doc = builder.parse(f);
Element root = doc.getDocumentElement();
NodeList children=root.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
Node child = children.item(i);
if (child instanceof Element)
{
Element childElement = (Element)child;
Text textNode = (Text) childElement.getFirstChild();
String text = textNode.getData().trim();
int size;
String name ;
if (childElement.getTagName().equals("name")){
name = text;
}
elseif (childElement.getTagName().equals("size")){
size = Integer.parseInt(text);
}
}
}
元素的第一个子节点就是一个文本元素。C++版本中也可以模仿java版本的处理:
DOMText* pDOMText=(DOMText*)pDOMElement->getFirstChild();
std::cout <<XMLString::transcode(pTmp->getNodeName())<<"="<<XMLString::transcode(pDOMText->getNodeValue())<<endl;
效果相同!
查看W3C或者Xerces的中文API文档
Xerces C++的文档都是英文的,看着费劲。我发现它的文档实际上和java JDK中的org.w3c.dom包下的接口相同。直接看JDK的中文API也是一样的!
Xerces C++中在所有的W3C类前面加上了DOM前缀。你可以按照这个规则在java JDK中找到相对应的类的java版的中文文档。
Xerces C++之所以使用DOM前缀,是因为老版本的Xerces C++并没有使用命名空间,新版本已经使用了命名空间XERCES_CPP_NAMESPACE。
查看本文来源