Xerces for C++ Using Visual C++, Part 2(转)

本文介绍如何利用Xerces-C++库在Visual Studio 2008中创建XML DOM文档,并演示了如何将文档输出到控制台或保存为文件。文章通过实例详细展示了创建节点、设置属性及文本内容的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自http://www.codeproject.com/KB/cpp/xerces_tutorial_02.aspx

Introduction

This tutorial shows you how to create an XML DOM document using Xerces for C++ using Visual Studio 9, and also how to output the results to a console, or save to a file. This tutorial produces the following output:

Collapse Copy Code
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Hello_World>
    <!-- Dates are formatted mm/dd/yy. Don't forget XML is case-sensitive. -->
    <data date="01/22/09" float="3.14159265" integer="65536">
        <row index="1">Comments and data can also go in text nodes.</row>
        <row description="The value of PI">3.1415926535897932384626433832795</row>
        <row website="http://www.ted.com.au/">TED - ideas worth sharing.</row>
    </data>
</Hello_World>

This tutorial assumes you have already downloaded the Xerces binaries, and have correctly configured your Visual Studio environment. If you need help with this, read my previous tutorial on the subject.

Include Files

For this tutorial, you will need the following includes at a minimum:

Collapse Copy Code
// Mandatory for using any feature of Xerces.
#include <xercesc/util/PlatformUtils.hpp>

// Use the Document Object Model (DOM) API
#include <xercesc/dom/DOM.hpp>

// Required for outputing a Xerces DOMDocument
// to a standard output stream (Also see: XMLFormatTarget)
#include <xercesc/framework/StdOutFormatTarget.hpp>

// Required for outputing a Xerces DOMDocument
// to the file system (Also see: XMLFormatTarget)
#include <xercesc/framework/LocalFileFormatTarget.hpp>

This tutorial also uses the following includes for creating sample data:

Collapse Copy Code
// (optional) The following includes
// are only used to create sample data in this tutorial.
#include <time.h>
#include <string>
#include <sstream>

Namespaces

The following line (without semi-colon) will expand to use the correct Xerces namespace. The alternative is to prefix all Xerces code and functions with the XERCES_CPP_NAMESPACE:: namespace.

Collapse Copy Code
// Define namespace symbols
XERCES_CPP_NAMESPACE_USE

Initializing Xerces and the DOM

Initialize Xerces, and get the DOM implementation used for creating DOM documents:

Collapse Copy Code
// Initilize Xerces.
XMLPlatformUtils::Initialize();

// Pointer to our DOMImplementation.
DOMImplementation * pDOMImplementation = NULL;

// Get the DOM Implementation (used for creating DOMDocuments).
// Also see: http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
pDOMImplementation = 
  DOMImplementationRegistry::getDOMImplementation(XMLString::transcode("core"));

Note: Both Xerces and Xalan follow the official specifications for the XML and XSLT languages. These can be found at the W3C.

Creating the DOM Document Using Xerces for C++

The following code block creates a DOM document and fills in some sample data. The sample data starts life as integers, floats, dates, or strings, but ultimately, everything must be converted to a wide-character string as required by Xerces.

Collapse Copy Code
// Pointer to a DOMDocument.
DOMDocument * pDOMDocument = NULL;

/*
Create an empty DOMDocument. When an empty document 
is created specify the namespace of the document (optional)
and also the root node. Both of these values can be any 
valid text (ie. no spaces or weird characters).
The "root node" in this example is "Hello_World". 
(XML is case-sensitive) This root node 
*owns everything* beneath it, just as if it were a separate object... 
in fact, it is. It's defined by the 'DOMNode' class.

NOTE: The namespace in this example happens to be a website
      within the 'example.com' domain [RFC2606]
      However, it does NOT have to be a domain name. 
      It could be your company name, or the name of your dog.
      It's just that domain names tend to be unique. 
      Since any name will do, there does not even have to 
      be a website at the address specified.
*/
pDOMDocument = pDOMImplementation->createDocument(L"schemas.example.com/2008/", 
                                                  L"ex:Hello_World", 0);

// If you're not interested in namespaces (and most of the time I'm not),
// just use the following line instead of the one above...
pDOMDocument = pDOMImplementation->createDocument(0, L"Hello_World", 0);


/*
=============================================================
Anything below this point is optional, 
although it would be a pretty boring and empty document!.
=============================================================

Since we are going to add nodes to the document's root, 
we need a pointer to this root node/element (which was
previously created when the document was created).

    Note: Due to their close relationship, 
    the words "node" and "element" are often used
    interchangably. Nodes are the base class, 
    and Elements are the specilizations.
*/
DOMElement * pRootElement = NULL;
pRootElement = pDOMDocument->getDocumentElement();


// Create a Comment node, and then append this to the root element.
DOMComment * pDOMComment = NULL;
pDOMComment = pDOMDocument->createComment(L"Dates are formatted mm/dd/yy." 
              L" Don't forget XML is case-sensitive.");
pRootElement->appendChild(pDOMComment);


// Create an Element node, then fill in some attributes,
// and then append this to the root element.
DOMElement * pDataElement = NULL;
pDataElement = pDOMDocument->createElement(L"data");

    // Copy the current system date to a buffer, then set/create the attribute.
    wchar_t wcharBuffer[128];
    _wstrdate_s(wcharBuffer, 9);
    pDataElement->setAttribute(L"date", wcharBuffer);

    // Convert an integer to a string, then set/create the attribute.
    _itow_s(65536, wcharBuffer, 128, 10);
    pDataElement->setAttribute(L"integer", wcharBuffer);

    // Convert a floating-point number to a wstring,
    // then set/create the attribute.
    std::wstringstream    myStream;
        myStream.precision(8);
        myStream.setf(std::ios_base::fixed, std::ios_base::floatfield);
        myStream << 3.1415926535897932384626433832795;
    const std::wstring ws(myStream.str());
    pDataElement->setAttribute(L"float", ws.c_str());
    
    // Append 'pDataElement' to 'pRootElement'.
    pRootElement->appendChild(pDataElement);


// Create an Element node, then fill in some attributes, add some text,
// then append this to the 'pDataElement' element.
DOMElement * pRow = NULL;
pRow = pDOMDocument->createElement(L"row");

    // Create some sample data.
    _itow_s(1, wcharBuffer, 128, 10);
    pRow->setAttribute(L"index", wcharBuffer);

    /*
    Create a text node and append this as well. Some people 
    prefer to place their data in the text node
    which is perfectly valid, others prefer to use 
    the attributes. A combination of the two is quite common.
    */
    DOMText* pTextNode = NULL;
    pTextNode = pDOMDocument->createTextNode(L"Comments and" 
                L" data can also go in text nodes.");
    pRow->appendChild(pTextNode);

    pDataElement->appendChild(pRow);


// Create another row (this time putting data and descriptions into different places).
pRow = pDOMDocument->createElement(L"row");
    pRow->setAttribute(L"description", L"The value of PI");
    pTextNode = pDOMDocument->createTextNode(L"3.1415926535897932384626433832795");
    pRow->appendChild(pTextNode);
    pDataElement->appendChild(pRow);


// Create another row.
pRow = pDOMDocument->createElement(L"row");
    pRow->setAttribute(L"website", L"http://www.ted.com.au/");
    pTextNode = pDOMDocument->createTextNode(L"TED - ideas worth sharing.");
    pRow->appendChild(pTextNode);
    pDataElement->appendChild(pRow);

Output the DOM Document to the Standard Output Stream

Collapse Copy Code
void DoOutput2Stream(DOMDocument* pmyDOMDocument)
{
    DOMImplementation    *pImplement    = NULL;
    DOMWriter        *pSerializer    = NULL;
    XMLFormatTarget        *pTarget    = NULL;

    /*
    Return the first registered implementation that has
    the desired features. In this case, we are after
    a DOM implementation that has the LS feature... or Load/Save.
    */
    pImplement = DOMImplementationRegistry::getDOMImplementation(L"LS");

    /*
    From the DOMImplementation, create a DOMWriter.
    DOMWriters are used to serialize a DOM tree [back] into an XML document.
    */
    pSerializer = ((DOMImplementationLS*)pImplement)->createDOMWriter();

    /*
    This line is optional. It just sets a feature
    of the Serializer to make the output
    more human-readable by inserting line-feeds and tabs, 
    without actually inserting any new nodes
    into the DOM tree. (There are many different features to set.) 
    Comment it out and see the difference.
    */
    pSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);

    /*
    Choose a location for the serialized output. The 3 options are:
        1) StdOutFormatTarget     (std output stream -  good for debugging)
        2) MemBufFormatTarget     (to Memory)
        3) LocalFileFormatTarget  (save to file)
        (Note: You'll need a different header file for each one)
    */
    pTarget = new StdOutFormatTarget();
    
    // Write the serialized output to the target.
    pSerializer->writeNode(pTarget, *pmyDOMDocument);
}

Save the DOM Document to the File System

Similar to the above section, use the following code to save a DOM document to the file system:

Collapse Copy Code
void DoOutput2File(DOMDocument* pmyDOMDocument, const wchar_t * FullFilePath )
{

    DOMImplementation    *pImplement        = NULL;
    DOMWriter            *pSerializer    = NULL;
    XMLFormatTarget        *pTarget        = NULL;

    /*
    Return the first registered implementation that 
    has the desired features. In this case, we are after
    a DOM implementation that has the LS feature... or Load/Save.
    */
    pImplement = DOMImplementationRegistry::getDOMImplementation(L"LS");

    /*
    From the DOMImplementation, create a DOMWriter.
    DOMWriters are used to serialize a DOM tree [back] into an XML document.
    */
    pSerializer = ((DOMImplementationLS*)pImplement)->createDOMWriter();


    /*
    This line is optional. It just sets a feature 
    of the Serializer to make the output
    more human-readable by inserting line-feeds, 
    without actually inserting any new elements/nodes
    into the DOM tree. (There are many different features to set.) 
    Comment it out and see the difference.
    */
    pSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);


    /*
    Choose a location for the serialized output. The 3 options are:
        1) StdOutFormatTarget     (std output stream -  good for debugging)
        2) MemBufFormatTarget     (to Memory)
        3) LocalFileFormatTarget  (save to file)
        (Note: You'll need a different header file for each one)
        Don't forget to escape file-paths with a backslash character, or
        just specify a file to be saved in the exe directory.
        
          eg. c://example//subfolder//pfile.xml

    */
    pTarget = new LocalFileFormatTarget(FullFilePath);


    // Write the serialized output to the target.
    pSerializer->writeNode(pTarget, *pmyDOMDocument);
}

Clean Up

Clean up as usual.

Collapse Copy Code
// Cleanup.
p_DOMDocument->release();
XMLPlatformUtils::Terminate();

Known Problems with Visual Studio 2008

I've encountered the following problem compiling and linking with Xerces using Visual Studio v9 (2008). To resolve the following error...

Collapse Copy Code
error LNK2001: unresolved external symbol
"__declspec(dllimport) public: static wchar_t *
__cdecl xercesc_2_7::XMLString::transcode(char const * const)" (
__imp_?transcode@XMLString@xercesc_2_7@@SAPA_WQBD@Z)

...modify the following C++ language compiler option:

Collapse Copy Code
/Zc:wchar_t (wchar_t Is Native Type)

History

  • Initial release: 2009-01-22.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Peter Wilson


Member
I've twice been the director/CEO/what-have-you of my own software companies. I sold software into 20 countries before I stopped counting.
Occupation: Software Developer (Senior)
Company: Various
Location: Australia Australia

Other popular C / C++ Language articles:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值