Click here to Skip to main content
Click here to Skip to main content

CXml - A Wrapping Class for MSXML 3.0/4.0/5.0/6.0

, 10 Jan 2013
Rate this:
Please Sign up or sign in to vote.
This wrapping class will try to use the latest version of MSXML in the machine, and it is easy because of using auto_ptr.

Introduction

MSXML, a window component shipped with Windows / Office and other Microsoft products, exists in all Windows platforms. But there are different versions of MSXML, from 2.6 to 6.0, which causes a lot of problems.

This is a wrapping class library for MSXML 3.0/4.0/5.0/6.0 consisting of resolving the above problem -- you don't need to worry about the available MSXML version on different machines any more. Also it provides an easy-to-use interface -- each node in the XML is considered an object and you can use some code like below to locate a node.  

xml.GetRoot()->GetChild(_T("a"))->GetChild(_T("b"))->GetChild(_T("c")) 

Sample Code

Please find the sample code in the demo project.

JW_CXml/demo.jpg

Using the Code

Copy all the files in the /CXml/*.* directory and add them into your project.

#include "Xml.h"
using namespace JWXml;

Here, I have added a namespace for the classes, you can change it as you like.

MSXML Version

The class will try to choose the version of MSXML in the following order:

hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument60) );
hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument30) );
hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument50) );
hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument40) );
hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument26) );
hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument) );

Classes Overview

CXml

class CXml
{
    friend class CXsl;

public:
    CXml(void);
    ~CXml(void);

protected:
    MSXML2::IXMLDOMDocument2Ptr m_pDoc;
    CString m_strFilePath;
    MSXML_VERSION m_emVersion;
    std::map< CString, CString> m_mpNamespace;

    BOOL CreateInstance(void);

public:
    // Open XML file
    BOOL Open(LPCTSTR lpszXmlFilePath);

    // Create a new XML file
    BOOL Create( LPCTSTR lpszRootName = _T("xmlRoot")
        , LPCTSTR lpszPrefix = _T("")
        , LPCTSTR lpszNamespaceURI = _T("")
        );

    // Load XML string
    BOOL LoadXml(LPCTSTR lpszXmlContent);

    // save XML file
    BOOL Save(LPCTSTR lpszFilePath);

    // save XML file with formatted output
    BOOL SaveWithFormatted(LPCTSTR lpszFilePath = NULL, 
            LPCTSTR lpszEncoding = _T("UTF-8"));

    // close XML file
    void Close(void);

    CString GetXmlFile(void) const;

    // Encode the binary data into string
    CString Base64Encode( LPBYTE pBuf, ULONG ulSize);

    // Decode the string into binary data
    BOOL Base64Decode( CString strIn, LPBYTE pBuf, LONG & lSize);

    // namespace
    void AddSelectionNamespace( LPCTSTR lpszPrefix, LPCTSTR lpszURI);

    // get the root element of
    CXmlNodePtr GetRoot(void);

    // get single node by XPath
    CXmlNodePtr SelectSingleNode(LPCTSTR lpszPath);

    // get nodes by XPath
    CXmlNodesPtr SelectNodes(LPCTSTR lpszPath);

    // create node
    CXmlNodePtr CreateNode(LPCTSTR lpszName
        , LPCTSTR lpszPrefix = _T("")
        , LPCTSTR lpszNamespaceURI = _T("")
        );

    // get the current version of MSXML
    MSXML_VERSION GetVersion(void) const;
};

CXmlNode

class CXmlNode
{
    friend class CXml;
    friend class CXmlNode;
    friend class CXmlNodes;

protected:
    MSXML2::IXMLDOMNodePtr m_pNode;

    CXmlNode( MSXML2::IXMLDOMNodePtr pNode);

    BOOL _GetValue(CString & strValue) const;
    BOOL _SetValue(CString & strValue) const;

    BOOL _GetAttribute( CString & strName, CString & strValue) const;
    BOOL _SetAttribute( CString & strName IN
                      , CString & strValue IN
                      , CString & strPrefix IN
                      , CString & strNamespaceURI IN
                      ) const;

public:

    CXmlNode(void);
    CXmlNode(const CXmlNode & refNode IN);
    CXmlNode(const CXmlNodePtr pNode IN);
    ~CXmlNode(void);

    CXmlNodePtr operator = (CXmlNodePtr pNode);
    CXmlNode & operator = (const CXmlNode & refNode);

    BOOL IsNull(void) const;     // Whether the current element exist
    CString GetName(void) const;// Get the name of the current node
    CXmlNode & Detach(void);    // Detach the current node
    void Release(void);    // Release this node

    CXmlNodePtr GetChild( CString strName, BOOL bBuildIfNotExist = TRUE);
    CXmlNodePtr NewChild( CString strName );
    CXmlNodePtr GetParent(void);
    CXmlNodesPtr GetChildren();
    void AttachChild( CXmlNodePtr & pChildNode);
    void AttachChild( CXmlNode & refChildNode);
    BOOL HasChildren(void);
    BOOL RemoveChildren(void);

    CString    GetAttribute( CString strName, LPCTSTR lpszDefault = NULL) const;
    bool    GetAttribute( CString strName, bool bDefault) const;
    int        GetAttribute( CString strName, int nDefault) const;
    long    GetAttribute( CString strName, long lDefault) const;
    __int64    GetAttribute( CString strName, __int64 llDefault) const;
    float    GetAttribute( CString strName, float fDefault) const;
    double    GetAttribute( CString strName, double dDefault) const;
    DWORD    GetAttribute( CString strName, DWORD dwDefault) const;

    BOOL    SetAttribute( CString strName, LPCTSTR lpszValue ,
            CString strPrefix = _T(""), CString strNamespaceURI = _T(""));
    BOOL    SetAttribute( CString strName, bool bValue ,
            CString strPrefix = _T(""), CString strNamespaceURI = _T(""));
    BOOL    SetAttribute( CString strName, int nValue ,
            CString strPrefix = _T(""), CString strNamespaceURI = _T(""));
    BOOL    SetAttribute( CString strName, long lValue ,
            CString strPrefix = _T(""), CString strNamespaceURI = _T(""));
    BOOL    SetAttribute( CString strName, __int64 llValue ,
            CString strPrefix = _T(""), CString strNamespaceURI = _T(""));
    BOOL    SetAttribute( CString strName, float fValue ,
            CString strPrefix = _T(""), CString strNamespaceURI = _T(""));
    BOOL    SetAttribute( CString strName, double dValue ,
            CString strPrefix = _T(""), CString strNamespaceURI = _T(""));
    BOOL    SetAttribute( CString strName, DWORD dwValue ,
            CString strPrefix = _T(""), CString strNamespaceURI = _T(""));

    BOOL RemoveAttribute( CString strName );

    CString    GetValue( LPCTSTR lpszDefault = NULL ) const;
    bool    GetValue( bool bDefault ) const;
    int        GetValue( int nDefault) const;
    long    GetValue( long lDefault) const;
    __int64    GetValue( __int64 llDefault) const;
    float    GetValue( float fDefault) const;
    double    GetValue( double dDefault) const;
    DWORD    GetValue( DWORD dwDefault) const;

    BOOL    SetValue( LPCTSTR lpszValue );
    BOOL    SetValue( bool bValue );
    BOOL    SetValue( int nValue );
    BOOL    SetValue( long lValue );
    BOOL    SetValue( __int64 llValue );
    BOOL    SetValue( float fValue );
    BOOL    SetValue( double dValue );
    BOOL    SetValue( DWORD dwValue );

    CXmlNodePtr SelectSingleNode(LPCTSTR lpszPath);
    CXmlNodesPtr SelectNodes(LPCTSTR lpszPath);

    CString GetOuterXml(void) const;
    CString GetInnerXml(void) const;
};

CXmlNodes

class CXmlNodes
{
    friend class CXml;
    friend class CXmlNode;
    friend class CXmlNodes;

public:
    ~CXmlNodes(void);
    CXmlNodes(void);
    CXmlNodes( const CXmlNodes & refNodes );
    CXmlNodes( CXmlNodesPtr pNodes );

    CXmlNodesPtr operator = (CXmlNodesPtr pNodes);
    CXmlNodes & operator = (const CXmlNodes & refNodes);
    CXmlNodePtr operator[] ( LONG lIndex );
    CXmlNodePtr operator[] ( LPCTSTR lpszName );

    LONG GetCount(void);
    void Release(void);

    CXmlNodePtr GetItem( LONG nIndex );
    CXmlNodePtr GetItem( LPCTSTR lpszName );

protected:
    CXmlNodes(MSXML2::IXMLDOMNodeListPtr pNodeList);
    MSXML2::IXMLDOMNodeListPtr m_pNodeList;

};

CXsl

class CXsl
{
public:
    CXsl(void);
    ~CXsl(void);

    // Open XSL file
    BOOL Open(LPCTSTR lpszXslFilePath);

    // close XSL file
    void Close(void);

    // transform to file
    BOOL TransformToFile( CXml & objXml, LPCTSTR lpszFilePath);

    // add a parameter
    BOOL AddParameter( LPCTSTR lpszParamName, LPCTSTR lpszParamValue, 
            LPCTSTR lpszNamespaceURI = NULL);

protected:
    MSXML2::IXSLTemplatePtr m_pIXSLTemplate;
    MSXML2::IXMLDOMDocument2Ptr m_pStyleSheet;
    MSXML2::IXSLProcessorPtr m_pIXSLProcessor;
};

History

  • v2.0
    • Created: 2007-07-16
  • v2.1
    • Added LoadXml method
    • Added GetVersion method
    • Added const for GetXXX methods
    • Defined ASSERT as ATLASSERT for ATL
    • Defined TRACE as ATLTRACE for ATL
  • V2.2
    • Added the parameter lpszRootName for CXml::Open
    • Removed CXml::GetLastError
    • Added CXml::AddNamespace
    • Added two new overrides for CXml::CreateNode with namespace support
  • V3.0
    • Added another copy constructor for CXmlNode and CXmlNodes
    • Added const modifier for some variables
    • Added CXmlNode::GetInnerXml
    • Added CXmlNode::GetOuterXml
    • Added CXml::Create
    • Changed the MSXML version for Create to 6.0 -> 3.0 -> 5.0 -> 4.0
    • Added namespace support for attributes
    • Added a new class named CXsl
  • V3.1
    • Add method CXml::SaveWithFormatted (Thanks to roel_)
    • Reuse CXml::SaveStreamToFile in CXsl::TransformToFile
    • Add CXsl::AddParameter to allow passing parameters to XSLT
    • Use std::tr1::shared_ptr if exists instead of std::auto_ptr
    • Change namespace from Generic to JWXml 
  • V3.2
    • Bug fix for the Create method usage in demo.
    • Upgrade to VS2010

License

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

Share

About the Author

Jerry.Wang
Team Leader
China China
Jerry is from China. He was captivated by computer programming since 13 years old when first time played with Q-Basic.
 

  • Windows / Linux & C++
  • iOS & Obj-C
  • .Net & C#
  • Flex/Flash & ActionScript
  • HTML / CSS / Javascript
  • Gaming Server programming / video, audio processing / image & graphics
 
Contact: vcer(at)qq.com
Chinese Blog: http://blog.csdn.net/wangjia184

Comments and Discussions

 
Bug求教,出现红色大X Pinmemberwuxianzhong13-Jul-14 5:59 
QuestionMissing some information about Canonilization PinmemberKarstenK4-Nov-13 20:57 
GeneralMy vote of 5 Pinmembermaplewang22-Jan-13 15:59 
GeneralMy vote of 5 Pinmemberskyformat99@gmail.com11-Jan-13 17:55 
GeneralRe: My vote of 5 PinmemberJerry.Wang12-Jan-13 13:50 
GeneralMy vote of 5 PinmemberH.Brydon10-Jan-13 8:51 
Question这个项目有人在版本低于6.0的MSXML环境下用过吗? Pinmemberdothan00925-Feb-12 1:37 
Question没有一个比较简便的demo么? Pinmemberyanzhiwei1475-Feb-12 20:47 
GeneralMy vote of 5 Pinmemberjerry_wangjh11-Nov-11 20:39 
GeneralMy vote of 5 Pinmembertankfun12-Sep-11 23:49 
Generalnew function - GetXML() PinmemberMaster^Tristar30-Mar-11 19:28 
GeneralRe: new function - GetXML() PinmemberJerry.Wang12-Apr-11 18:45 
GeneralRe: new function - GetXML() Pinmemberhazywxin226-May-11 5:06 
GeneralMy vote of 5 PinmemberJhomes14-Feb-11 11:21 
AnswerAdded two new functions: GetAttributeCount PinmemberLars [Large] Werner19-Dec-10 9:49 
Generaland GetAttributeByIndex PinmemberLars [Large] Werner19-Dec-10 9:51 
GeneralRe: and GetAttributeByIndex PinmemberJerry.Wang12-Apr-11 18:48 
QuestionIf I call _tsplitpath first then call CXmlNode::SetAttribute(strName, lpszValue). It's default parameter will have some value. why? Pinmembersilvonli15-Nov-10 21:56 
GeneralGood job, if you provide more sample is better Pinmembermaplewang26-Oct-10 0:59 
Question不支持命名空间? Pinmemberhellohuhu6-Apr-10 23:26 
AnswerRe: 不支持命名空间? PinmemberJerry.Wang7-Jul-10 16:34 
Question如何解决缩进的问题?? Pinmemberzhuliyan23-Feb-10 21:39 
AnswerRe: 如何解决缩进的问题?? PinmemberJerry.Wang8-Mar-10 16:35 
Question如何解决缩进的问题?? Pinmemberzhuliyan23-Feb-10 21:37 
GeneralHeap corruption detected PinmemberSnakefoot8-Dec-09 11:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140821.2 | Last Updated 10 Jan 2013
Article Copyright 2007 by Jerry.Wang
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid