科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件使用W3C标准的DOM处理XML文件

使用W3C标准的DOM处理XML文件

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

Xerces是一个完全符合W3C的DOM标准的项目。它完全提供了W3C的DOM标准规定的接口。 在Java的JDK中提供的也是一个W3C的DOM标准接口。

作者:良少shendl 来源:CSDN 2008年2月1日

关键字: XML 处理 DOM W3C标准 Linux

  • 评论
  • 分享微博
  • 分享邮件
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
 
查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章