xerces解析和创建xml文件

来源:互联网 发布:淘宝产品权重 编辑:程序博客网 时间:2024/06/03 04:08
/*
作者:刘*
日期:20131217
文件名:ParserXml3.h
vs2008 Debug 工程设置要点:
Xerces3.1=E:\study\myxml\xerces-c-3.1.1-x86-windows-vc-8.0
include:$(Xerces3.1)/include
lib:
  文件:xerces-c_3.lib
  路径:$(Xerces3.1)/lib
dll:xerces-c_3_1.dll与可执行文件放在同一个目录
lib和dll都选了release版的,能运行成功,好奇怪!
备注:对库2.8,做相同的工程设置,编译链接能成功,但是无法运行;可能工程设置有问题,也有可能lib or dll 文件选取的不对。本文参考了其他文章
*/
#include <stdio.h>
#include "xercesc/dom/DOM.hpp"
#include "xercesc/dom/DOMNode.hpp"
#include "xercesc/dom/DOMDocument.hpp"
#include "xercesc/dom/DOMDocumentType.hpp"
#include "xercesc/dom/DOMElement.hpp"
#include "xercesc/dom/DOMImplementation.hpp"
#include "xercesc/dom/DOMImplementationLS.hpp"
#include "xercesc/dom/DOMNodeIterator.hpp"
#include "xercesc/dom/DOMNodeList.hpp"
#include "xercesc/dom/DOMText.hpp"
#include "xercesc/parsers/XercesDOMParser.hpp"
#include "xercesc/util/XMLUni.hpp"

#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/StdOutFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
//输出到文件需要这个头文件
#include <xercesc/framework/LocalFileFormatTarget.hpp> 

using namespace std;
using namespace XERCES_CPP_NAMESPACE;

#ifdef _DEBUG
#pragma comment( lib, "xerces-c_3D.lib" )
#else
#pragma comment( lib, "xerces-c_3.lib" )
#endif

//一个使用实例 http://blog.csdn.net/liuchang5/article/details/5775648
//http://blog.csdn.net/jfkidear/article/details/6863328

#define FILE_NAME "test.xml"
#define _2C XMLString::transcode
#define _X(str) XStr(str).unicodeForm()

class CMyXml
{
public:
  CMyXml();
  ~CMyXml();

  bool ParserXML();
  bool WriteXML();
  void DisHex(char * Str);

private:
    XercesDOMParser * m_DOMXmlParser;
};

class XStr
{
public:
    XStr(const char* const toTranscode)
    {
        fUnicodeForm = XMLString::transcode(toTranscode);
    }
    ~XStr()
    {
        XMLString::release(&fUnicodeForm);
    }
    const XMLCh* unicodeForm() const
    {
        return fUnicodeForm;
    }
private:
    XMLCh*   fUnicodeForm;
};

//文件名:ParserXml3.cpp
#include "ParserXml3.h"
#include <iostream>

CMyXml::CMyXml()
{
    try
    {  
        // Initialize Xerces-C++ library
        XMLPlatformUtils::Initialize();
    }
    catch(XMLException & excp) 
    {
        char* msg = _2C(excp.getMessage());
        printf("XML toolkit initialization error: %s/n", msg);
        XMLString::release(&msg);
    } 
    m_DOMXmlParser = new XercesDOMParser();
}

CMyXml::~CMyXml()
{
    if (m_DOMXmlParser!=NULL)
    {
        delete(m_DOMXmlParser);
        m_DOMXmlParser = NULL;
    }
    try
    {       
        XMLPlatformUtils::Terminate();//销毁平台 ,可以修在析构方法中。
    }
    catch(XMLException& excp)
    {
        char* msg = _2C(excp.getMessage());
        printf("XML toolkit terminate error: %s/n", msg);
        XMLString::release(&msg);
    }
}

bool CMyXml::ParserXML()
{
    m_DOMXmlParser->setValidationScheme(XercesDOMParser::Val_Auto );
    m_DOMXmlParser->setDoNamespaces( false );
    m_DOMXmlParser->setDoSchema( false );
    m_DOMXmlParser->setLoadExternalDTD( false );

    m_DOMXmlParser->parse("test.xml");
    //得到文件对象
    DOMDocument *xmlDoc = m_DOMXmlParser->getDocument();
    DOMElement * Root=xmlDoc->getDocumentElement();

    //根节点为空
    if(!Root) //getDocumentElement用来得到文件根节点
    {
        delete(m_DOMXmlParser);
        m_DOMXmlParser = NULL;
        return false;
    }
    char *sEncoding = _2C(xmlDoc->getXmlEncoding());
    char *sVersion  = _2C(xmlDoc->getXmlVersion());
    //char *sURI = _2C(xmlDoc->getDocumentURI());
    char *sRootName = _2C(Root->getNodeName());
    if (Root->getNodeType() == DOMNode::ELEMENT_NODE)
    {
        printf("this is a element node\n");
    }
    
    char *sRootVal = _2C(Root->getTextContent());

    printf("<xml version='%s' encoding='%s' URI=''>\n",sEncoding,sVersion);
    printf("<%s>%s\n",sRootName,sRootVal);
    
    //Root->getFirstChild();
    //Root->getLastChild();
    DOMNodeList * nodelist=Root->getChildNodes();
    int nSize = nodelist->getLength();
    printf("child node count =%d\n",nSize);

    //得到code 节点 当对应多个 code节点时 则是 nodelist 可用循环遍历,这里只有一个code 就去 item(0)的值    getElementsByTagName 方法很好
    DOMNode* xCode = xmlDoc->getElementsByTagName(_2C("CODE"))->item(0);
    //取得属性的名称  TEXT
    char *aa = _2C(xCode->getAttributes()->item(0)->getNodeName());
    //得到属性的值 (每个节点的第一个子节点都是它的值,即便这个值为空,当当前节点是TEXT_NODE属性时 ,才能得到getNodeValue的值) 这是取TEXT 属性的值,取结点的值 方法相同
    char* bb = _2C(xCode->getAttributes()->item(0)->getFirstChild()->getNodeValue());
    //第二个 属性
    char *cc = _2C(xCode->getAttributes()->item(1)->getNodeName());
    char* dd = _2C(xCode->getAttributes()->item(1)->getFirstChild()->getNodeValue());
    printf("  <CODE %s=%s,%s=%s>\n",aa,bb,cc,dd);

    //读取state节点值
    DOMNodeList * nodelist2 = xmlDoc->getElementsByTagName(_2C("STATE"));
    DOMNode *xState = nodelist2->item(0);//同样只有一个节点,直接取0
    char * str_name = _2C(xState->getNodeName()); //可以用来取节点名称
    char * str_state = _2C(xState->getFirstChild()->getNodeValue());//_2C 用于字符转换 XMLch转为  string 或者 char*
    printf("  <%s=%s> \n",str_name,str_state);
    return true;
}

bool CMyXml::WriteXML()
{
    char * StudentName[3]={"刘1","李2","刘3"};
    char * StudentID[3]={"19870902","19860406","20131028"};
    XMLCh str[10];
    // Do your actual work with Xerces-C++ here.
    _2C("Core", str, 9);
    DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(str);//DOMImplementation::getImplementation();
    DOMLSOutput* output = ((DOMImplementationLS*)impl)->createLSOutput();
    DOMLSSerializer*  serial = ((DOMImplementationLS*)impl)->createLSSerializer();
    //StdOutFormatTarget* target = new StdOutFormatTarget());         //输出到屏幕没有测试过
    //MemBufFormatTarget* target = new MemBufFormatTarget();          //输出到屏幕
    XMLFormatTarget *target = new LocalFileFormatTarget("write.xml"); //输出到文件
    output->setByteStream(target);
    
    DOMDocument * doc = impl->createDocument(0,_X("学生列表"),0);
    doc->setXmlStandalone(true);
    doc->setXmlVersion(_X("1.0"));

    //处理根节点
    DOMElement * Root = doc->getDocumentElement();
    Root->setAttribute(_2C("id"),_2C("1"));   //用_2C同样能处理字符串转换?_X可以不需要
    Root->setTextContent(_2C("node1")); 
    Root->setAttribute(_X("xmlns"), _X("com:cmcc:corporation"));
    Root->setAttribute(_X("xmlns:xsi"), _X("http://www.w3.org/2001/XMLSchema-instance"));
    Root->setAttribute(_X("xsi:schemaLocation"), _X("com:cmcc:corporation corporation.xsd"));

    //添加学生子节点
    for (int i=0;i<3;i++)
    {
        DOMNode * node=doc->createElement(_X("学生"));
        Root->appendChild(node);
    }

    DOMNodeList * nodelist = doc->getElementsByTagName(_X("学生"));
    int nSize =  nodelist->getLength();
    for (int k=0;k<nSize;k++)
    {
        DOMNode * node = nodelist->item(k);
        if (node->getNodeType() == DOMNode::ELEMENT_NODE)
        {
            DOMElement * ElementNode = (DOMElement*)node;
            DOMNode * nodename=doc->createElement(_X("姓名"));
            DOMNode * nodeID =doc->createElement(_X("学号"));
            nodename->appendChild(doc->createTextNode(_X(StudentName[k])));
            nodeID->appendChild(doc->createTextNode(_X(StudentID[k])));
            ElementNode->appendChild(nodename);
            ElementNode->appendChild(nodeID);
        }
    }

    serial->write(doc, output);

    doc->release();
    serial->release();
    delete target;
    return true;
}

void CMyXml::DisHex(char * sName)
{
    printf("%s(%d) = 0X",sName,strlen(sName));
    for (unsigned int i=0;i<strlen(sName);i++)
    {
        printf("%X",sName[i]&0xFF);
    }
    printf("\n");
    
}
int main()
{
    printf("Test how to parser and write a xml file\n");
    
    CMyXml cmyxml;
    //测试打印字符串16进制编码的函数
    cmyxml.DisHex("3刘33");
    cmyxml.ParserXML();
    cmyxml.WriteXML();
}
//test.xml
<?xml version="1.0" encoding="GBK" ?>
<NS>Newthon
    <CODE TEST="456" VALUE="789">123</CODE> 
    <RSPTIME>abc</RSPTIME> 
    <STATE>1</STATE>
    <MSG>edg</MSG>
</NS>
0 0
原创粉丝点击