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

来源:互联网 发布:监控平台用什么编程 编辑:程序博客网 时间:2024/06/05 03:14

转自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 symbolsXERCES_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.htmlpDOMImplementation =   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 waspreviously 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: VariousLocation: Australia Australia

Other popular C / C++ Language articles:

  • Member Function Pointers and the Fastest Possible C++ Delegates
    A comprehensive tutorial on member function pointers, and an implementation of delegates that generates only two ASM opcodes!
  • How a C++ compiler implements exception handling
    An indepth discussion of how VC++ implements exception handling. Source code includes exception handling library for VC++.
  • A Beginner's Guide to Pointers
    An article showing the use of pointers in C and C++
  • XML class for processing and building simple XML documents
    Link CMarkup into your VC++ app and avoid complex XML tools and dependencies
  • PugXML - A Small, Pugnacious XML Parser
    Discussion of techniques for fast, robust, light-weight XML parsing.