VC解析XML

 

 

#pragma once
#include "./XmlNode.h"
#include "./Xsl.h"
#include


//-------------------------------------------------------------------------
// Classes Name     :CXml CXmlNode CXmlNodes
// Author   :Jerry.Wang
//     :QQ = 32775973
//     :Email = [email protected]
//     :MSN = [email protected]
// CreateTime       :2005-10-23
// Version          :v2.0 2007-07-16
//     :v2.1 Improve: Add LoadXml method
//     :  Improve: Add GetVersion method
//     :  Improve: Add const for GetXXX methods
//     :  Improve: define ASSERT as ATLASSERT for ATL
//     :  Improve: define TRACE as ATLTRACE for ATL
//     :V2.2 Improve: Add the parameter lpszRootName for the CXml::Open
//     :  Improve: Remove the CXml::GetLastError
//     :  Improve: Add the CXml::AddNamespace
//     :  Improve: Add two new overrides for the CXml::CreateNode with namespace support
//     :V3.0 Improve: Add another copy constructor for CXmlNode and CXmlNodes
//     :  Improve: Add const modifier for some variables
//     :  Improve: Add CXmlNode::GetInnerXml
//     :  Improve: Add CXmlNode::GetOuterXml
//     :  Improve: Add the CXml::Create
//     :  Improve: Change the MSXML version for create to 6.0 -> 3.0 -> 5.0 -> 4.0
//     :  Improve: Add namespace support for attribute
//     :  Improve: Add a new class named CXsl
//     :V3.1 Improve: Add new method CXml::SaveWithFormatted(Thx to roel_)
//     :  Improve: Reuse CXml::SaveStreamToFile in CXsl::TransformToFile
//     :  Improve: Add CXsl::AddParameter to allow passing parameters to XSLT
//     :  Improve: Use std::tr1::shared_ptr if exists instead of std::auto_ptr
//     :  Improve: Change namespace from Generic to JWXml
//-------------------------------------------------------------------------

 

 

namespace JWXml
{
 typedef enum
 {
  MSXML_UNKNOWN = 00,
  MSXML26   = 26,
  MSXML30   = 30,
  MSXML40   = 40,
  MSXML50   = 50,
  MSXML60   = 60,
 } MSXML_VERSION;

 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 with formatted output
  BOOL Save(LPCTSTR lpszFilePath);
  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;

  // whether file exist
  static BOOL IsFileExist(CString strFilePath);

  // save the stream to file
  static BOOL SaveStreamToFile(IStream * pStream, LPCTSTR lpszFilePath);

  //add by fjm 20110927
  CString GetXml() const; //获取xml串
  void SetSync(BOOL);
 };
}

===========.cpp=====

#include "StdAfx.h"
#include "./xml.h"
#include


namespace JWXml
{
 CXml::CXml(void)
 : m_strFilePath(_T(""))
 , m_pDoc(NULL)
 , m_emVersion(MSXML_UNKNOWN)
 {
 }

 CXml::~CXml(void)
 {
  Close();
 }

 //-------------------------------------------------------------------------
 // Function Name    :IsFileExist [static]
 // Parameter(s)     :CString strFilePath
 // Return           :BOOL
 // Memo             :Whether the file exist
 //-------------------------------------------------------------------------
 BOOL CXml::IsFileExist(CString strFilePath)
 {
  BOOL bExist = FALSE;
  HANDLE hFile = NULL;

  hFile = CreateFile( strFilePath
   , GENERIC_READ
   , FILE_SHARE_READ | FILE_SHARE_WRITE
   , NULL
   , OPEN_EXISTING
   , 0
   , 0
   );

  if( hFile != INVALID_HANDLE_VALUE )
  {
   CloseHandle( hFile );
   bExist = TRUE;
  }

  return (bExist);
 }


 //-------------------------------------------------------------------------
 // Function Name    :CreateInstance
 // Parameter(s)     :
 // Return           :
 // Create   :2007-8-2 9:22 Jerry.Wang
 // Memo             :Create the MSXML instance
 //-------------------------------------------------------------------------
 BOOL CXml::CreateInstance(void)
 {
  Close();

  HRESULT hr = S_FALSE;

  hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument60) );
  m_emVersion = (m_emVersion == 0 && hr == S_OK) ? MSXML60 : m_emVersion; 
  hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument30) );
  m_emVersion = (m_emVersion == 0 && hr == S_OK) ? MSXML30 : m_emVersion;
  hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument50) );
  m_emVersion = (m_emVersion == 0 && hr == S_OK) ? MSXML50 : m_emVersion;
  hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument40) );
  m_emVersion = (m_emVersion == 0 && hr == S_OK) ? MSXML40 : m_emVersion;  
  hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument26) );
  m_emVersion = (m_emVersion == 0 && hr == S_OK) ? MSXML26 : m_emVersion;
  hr = (hr == S_OK) ? hr : m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument) );
  m_emVersion = (m_emVersion == 0 && hr == S_OK) ? MSXML_UNKNOWN : m_emVersion;
  if( hr != S_OK )
  {
   // did u CoInitialize ?
   // did u install MSXML?
   ASSERT(FALSE);
   return FALSE;
  }

  m_pDoc->setProperty( _bstr_t(_T("SelectionLanguage")), _variant_t(_T("XPath")) ); // 3.0 only
  if( m_emVersion == MSXML40 )
   m_pDoc->setProperty( _bstr_t(_T("NewParser")), _variant_t(true) );

  m_pDoc->setProperty( _bstr_t(_T("AllowXsltScript")), _variant_t(true));
  m_pDoc->setProperty( _bstr_t(_T("AllowDocumentFunction")), _variant_t(true));
  m_pDoc->resolveExternals = VARIANT_TRUE;
  m_pDoc->preserveWhiteSpace = VARIANT_FALSE;
  m_pDoc->validateOnParse = VARIANT_FALSE;
  m_strFilePath = _T("");
  m_mpNamespace.clear();

  return TRUE;
 }

 //-------------------------------------------------------------------------
 // Function Name    :Open
 // Parameter(s)     :LPCTSTR lpszXmlFilePath
 //     :LPCTSTR lpszRootName  The name of the root element if create
 // Return           :BOOL  false when failed
 // Memo             :open xml file, if not exist then create a new one
 //-------------------------------------------------------------------------
 BOOL CXml::Open( LPCTSTR lpszXmlFilePath )
 {
  HRESULT hr = S_FALSE;

  if( !IsFileExist(lpszXmlFilePath) )
   return FALSE;

  if( !CreateInstance() )
   return FALSE;

  m_strFilePath = lpszXmlFilePath;
  VARIANT_BOOL vbSuccessful = VARIANT_TRUE;

  try
  {
   vbSuccessful = m_pDoc->load( _variant_t(lpszXmlFilePath) );
  }
  catch( _com_error e )
  {
   TRACE( _T("CXml::Open( %s ) failed:%s\n"), lpszXmlFilePath, e.ErrorMessage());
   vbSuccessful = FALSE;
   ASSERT( FALSE );
  }
  catch(...)
  {
   vbSuccessful = FALSE;
   ASSERT( FALSE );
  }

  return (vbSuccessful == VARIANT_TRUE);
 }

 //-------------------------------------------------------------------------
 // Function Name    :Create
 // Parameter(s)     :lpszRootName  The name of the root node
 //     :lpszPrefix   The prefix of the root node [optional]
 //     :lpszNamespaceURI The namespace URL of the root node [optional]
 // Return           :BOOL
 // Create   :2008-1-16 14:22 Jerry.Wang
 // Memo             :Create a new xml file
 //-------------------------------------------------------------------------
 BOOL CXml::Create( LPCTSTR lpszRootName /* = _T("xmlRoot") */
  , LPCTSTR lpszPrefix /* = _T("") */
  , LPCTSTR lpszNamespaceURI /* = _T("") */
  )
 {
  HRESULT hr = S_FALSE;

  if( !CreateInstance() )
   return FALSE;

  m_strFilePath = _T("");
  VARIANT_BOOL vbSuccessful = VARIANT_TRUE;
  try
  {
   MSXML2::IXMLDOMProcessingInstructionPtr pPI = NULL;
   pPI = m_pDoc->createProcessingInstruction( _bstr_t(_T("xml")), _bstr_t(_T("version=\"1.0\" ")) );
   if( pPI == NULL )
   {
    ASSERT(FALSE);
    return FALSE;
   }

   m_pDoc->appendChild(pPI);

   // create the root element
   CXmlNode root = CreateNode( lpszRootName, lpszPrefix, lpszNamespaceURI);
   m_pDoc->appendChild(root.m_pNode);

   vbSuccessful = SUCCEEDED(hr) ? VARIANT_TRUE : VARIANT_FALSE;
  }
  catch( _com_error e )
  {
   TRACE( _T("CXml::Create( %s, %s, %s) failed:%s\n")
    , lpszRootName
    , lpszPrefix
    , lpszNamespaceURI
    , e.ErrorMessage()
    );
   vbSuccessful = FALSE;
   ASSERT( FALSE );
  }
  catch(...)
  {
   vbSuccessful = FALSE;
   ASSERT( FALSE );
  }

  return (vbSuccessful == VARIANT_TRUE);
 }

 //-------------------------------------------------------------------------
 // Function Name    :LoadXml
 // Parameter(s)     :LPCTSTR lpszXmlContent
 // Return           :BOOL
 // Memo             :Load the xml content
 //-------------------------------------------------------------------------
 BOOL CXml::LoadXml(LPCTSTR lpszXmlContent)
 {
  if( !CreateInstance() )
   return FALSE;

  VARIANT_BOOL vbSuccessful = VARIANT_TRUE;

  try
  {
   vbSuccessful = m_pDoc->loadXML( _bstr_t(lpszXmlContent) );
  }
  catch( _com_error e )
  {
   TRACE( _T("CXml::LoadXml failed:%s\n"), e.ErrorMessage());
   vbSuccessful = FALSE;
   ASSERT( FALSE );
  }
  catch(...)
  {
   vbSuccessful = FALSE;
   ASSERT( FALSE );
  }

  return (vbSuccessful == VARIANT_TRUE);
 }


 //-------------------------------------------------------------------------
 // Function Name    :Close
 // Parameter(s)     :void
 // Return           :void
 // Memo             :Release
 //-------------------------------------------------------------------------
 void CXml::Close(void)
 {
  m_mpNamespace.clear();
  m_strFilePath = _T("");
  m_emVersion = MSXML_UNKNOWN;
  RELEASE_PTR(m_pDoc);
 }


 

 //-------------------------------------------------------------------------
 // Function Name    :GetXmlFile
 // Parameter(s)     :void
 // Return           :CString
 // Create   :2008-1-16 10:58 Jerry.Wang
 // Memo             :Get the path of the xml file
 //-------------------------------------------------------------------------
 CString CXml::GetXmlFile(void) const
 {
  return m_strFilePath;
 }


 //-------------------------------------------------------------------------
 // Function Name    :CreateNode
 // Parameter(s)     :LPCTSTR lpszName   node local name
 //     :LPCTSTR lpszPrefix   node prefix
 //     :LPCTSTR lpszNamespaceURI namespace URI
 // Return           :CXmlNodePtr
 // Create   :2007-8-2 9:59 Jerry.Wang
 //-------------------------------------------------------------------------
 CXmlNodePtr CXml::CreateNode(LPCTSTR lpszName
  , LPCTSTR lpszPrefix /* = _T("") */
  , LPCTSTR lpszNamespaceURI /* = _T("") */
  )
 {
  ASSERT( m_pDoc != NULL );
  
  CXmlNodePtr pChild( new CXmlNode() );

  CString strName;
  strName.Format( _tcslen(lpszPrefix) > 0 ? _T("%s:%s") : _T("%s%s"), lpszPrefix, lpszName);
  try
  { 
   MSXML2::IXMLDOMNodePtr pChildNode = NULL;
   pChildNode = m_pDoc->createNode(_variant_t(_T("element")), _bstr_t(strName), _bstr_t(lpszNamespaceURI) );
   ASSERT( pChildNode != NULL );
   pChild->m_pNode = pChildNode;
   RELEASE_PTR(pChildNode);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXml::CreateNode( %s, %s, %s) failed:%s\n"), lpszName, lpszPrefix, lpszNamespaceURI, e.ErrorMessage());
   ASSERT( FALSE );
  }
  return pChild;
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :AddSelectionNamespace
 // Parameter(s)     :LPCTSTR lpszPrefix The prefix, should not contain xmlns
 //     :LPCTSTR lpszURI
 // Return           :
 // Create   :2007-8-1 18:06 Jerry.Wang
 // Memo             :Add the selection namespace for the XPath
 //-------------------------------------------------------------------------
 void CXml::AddSelectionNamespace( LPCTSTR lpszPrefix, LPCTSTR lpszURI)
 {
  ASSERT( m_pDoc != NULL );

  try
  {
   m_mpNamespace[lpszPrefix] = lpszURI;
   CString strNamespaces = _T("");
   std::map< CString, CString>::iterator iter;
   for( iter = m_mpNamespace.begin(); iter != m_mpNamespace.end(); iter++)
   {
    CString strNamespace;
    strNamespace.Format( _T("xmlns:%s='%s' "), iter->first, iter->second);

    strNamespaces += strNamespace;
   }

   m_pDoc->setProperty( _T("SelectionNamespaces"), _variant_t((LPCTSTR)strNamespaces));
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXml::AddNamespace( %s, %s) failed:%s\n"), lpszPrefix, lpszURI, e.ErrorMessage());
   ASSERT( FALSE );
  }
 }

 
 //-------------------------------------------------------------------------
 // Function Name    :GetRoot
 // Parameter(s)     :
 // Return           :
 // Memo             :get the root element
 //-------------------------------------------------------------------------
 CXmlNodePtr CXml::GetRoot(void)
 { 
  ASSERT( m_pDoc != NULL );

  CXmlNodePtr pNode( new CXmlNode() );

  try
  {
   MSXML2::IXMLDOMElementPtr pElement = NULL;
   HRESULT hr = m_pDoc->get_documentElement(&pElement);
   ASSERT( SUCCEEDED(hr) );
   ASSERT( pElement != NULL );

   pNode->m_pNode = pElement;
   RELEASE_PTR(pElement);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXml::GetRoot failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
  
  return pNode;
 }


 //-------------------------------------------------------------------------
 // Function Name    :SaveWithFormatted
 // Parameter(s)     :LPCTSTR lpszFilePath [in, optional]
 // Return           :BOOL
 // Memo             :Save the xml file
 //-------------------------------------------------------------------------
 BOOL CXml::Save(LPCTSTR lpszFilePath)
 {
  if( m_pDoc == NULL )
  {
   ASSERT(FALSE);
   return FALSE;
  }

  HRESULT hr = S_OK;

  try
  {
   if( lpszFilePath == NULL )
   {
    ASSERT(!m_strFilePath.IsEmpty());
    hr = m_pDoc->save( _variant_t((LPCTSTR)m_strFilePath) );
   }
   else
   {
    hr = m_pDoc->save( _variant_t( lpszFilePath ) );
    if( SUCCEEDED(hr) )
     m_strFilePath = lpszFilePath;
   }
   return SUCCEEDED(hr);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXml::Save( %s ) failed:%s\n"), lpszFilePath, e.ErrorMessage());
   ASSERT( FALSE );
   hr = e.Error();
  }

  return SUCCEEDED(hr);
 }

 //-------------------------------------------------------------------------
 // Function Name    :SaveWithFormatted
 // Parameter(s)     :LPCTSTR lpszFilePath [in, optional]
 //     :LPCTSTR lpszEncoding [in, optional]
 // Return           :BOOL
 // Memo             :Save the xml file in formatted
 // History   :V3.1 Thanks roel_'s advice to support formatted output
 //-------------------------------------------------------------------------
 BOOL CXml::SaveWithFormatted(LPCTSTR lpszFilePath /* = NULL */, LPCTSTR lpszEncoding /* = _T("UTF-8") */)
 {
  if( m_pDoc == NULL )
  {
   ASSERT(FALSE);
   return FALSE;
  }

  HRESULT hr = S_OK;

  MSXML2::IMXWriterPtr pMXWriter = NULL;
  MSXML2::ISAXXMLReaderPtr pSAXReader = NULL;
  MSXML2::ISAXContentHandlerPtr pISAXContentHandler = NULL;
  MSXML2::ISAXErrorHandlerPtr pISAXErrorHandler = NULL;
  MSXML2::ISAXDTDHandlerPtr pISAXDTDHandler = NULL;
  try
  {
  
   // create
   hr = pMXWriter.CreateInstance( __uuidof(MSXML2::MXXMLWriter));
   if( FAILED(hr) ){ ASSERT(FALSE); goto lblErrorHandlerForSave; }
   
   hr = pSAXReader.CreateInstance( __uuidof(MSXML2::SAXXMLReader));
   if( FAILED(hr) ){ ASSERT(FALSE); goto lblErrorHandlerForSave; }

   // save in formatted
   pISAXContentHandler = pMXWriter;
   pISAXErrorHandler = pMXWriter;
   pISAXDTDHandler = pMXWriter;

   if (FAILED (pMXWriter->put_omitXMLDeclaration (VARIANT_FALSE)) ||
    FAILED (pMXWriter->put_standalone (VARIANT_FALSE)) ||
    FAILED (pMXWriter->put_indent (VARIANT_TRUE)) ||
    FAILED (pMXWriter->put_encoding(_bstr_t(lpszEncoding)) )
    )
   {
    ASSERT(FALSE);
    goto lblErrorHandlerForSave;
   }

   if (FAILED(pSAXReader->putContentHandler (pISAXContentHandler)) ||
    FAILED(pSAXReader->putDTDHandler (pISAXDTDHandler)) ||
    FAILED(pSAXReader->putErrorHandler (pISAXErrorHandler)) ||
    FAILED(pSAXReader->putProperty ((unsigned short*)L"http://xml.org/sax/properties/lexical-handler", _variant_t(pMXWriter.GetInterfacePtr()))) ||
    FAILED(pSAXReader->putProperty ((unsigned short*)L"http://xml.org/sax/properties/declaration-handler", _variant_t(pMXWriter.GetInterfacePtr()))))
   {
    ASSERT(FALSE);
    goto lblErrorHandlerForSave;
   }
      
   IStream * pOutStream = NULL;
   ::CreateStreamOnHGlobal( NULL, TRUE, &pOutStream);
   hr = pMXWriter->put_output(_variant_t(pOutStream));
   if( FAILED(hr) ){ ASSERT(FALSE); goto lblErrorHandlerForSave; }

   hr = pSAXReader->parse(m_pDoc.GetInterfacePtr());
   if( FAILED(hr) ){ ASSERT(FALSE); goto lblErrorHandlerForSave; }
     
   if( lpszFilePath == NULL )
   {
    ASSERT(!m_strFilePath.IsEmpty());
    if( !CXml::SaveStreamToFile( pOutStream, m_strFilePath) )
     return FALSE;
   }
   else
   {
    if( !CXml::SaveStreamToFile( pOutStream, lpszFilePath) )
     return FALSE;
    m_strFilePath = lpszFilePath;
   }   
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXml::SaveWithFormatted( %s ) failed:%s\n"), lpszFilePath, e.ErrorMessage());
   ASSERT( FALSE );
   hr = e.Error();
  }

lblErrorHandlerForSave:
  RELEASE_PTR(pISAXDTDHandler);
  RELEASE_PTR(pISAXErrorHandler);
  RELEASE_PTR(pISAXContentHandler);
  RELEASE_PTR(pSAXReader);
  RELEASE_PTR(pMXWriter);

  return SUCCEEDED(hr);
 }

 //-------------------------------------------------------------------------
 // Function Name    :SaveStreamToFile
 // Parameter(s)     :IStream * pStream
 //     :LPCTSTR lpszFilePath
 // Return           :BOOL
 // Memo             :Save IStream to file, this method is inner used by JWXml
 //-------------------------------------------------------------------------
 BOOL CXml::SaveStreamToFile(IStream * pStream, LPCTSTR lpszFilePath)
 {
  HRESULT hr = S_OK;
  LPVOID pOutput = NULL;
  HGLOBAL hGlobal = NULL;

  hr = ::GetHGlobalFromStream( pStream, &hGlobal);
  if( FAILED(hr) ) { ASSERT(FALSE); return FALSE; }
  ::GlobalUnlock(hGlobal);
  LARGE_INTEGER llStart = {0, 0};
  ULARGE_INTEGER ullSize = {0, 0};
  pStream->Seek( llStart, STREAM_SEEK_CUR, &ullSize);
  pOutput = ::GlobalLock(hGlobal);

  HANDLE hFile = ::CreateFile( lpszFilePath
   , GENERIC_WRITE
   , FILE_SHARE_WRITE | FILE_SHARE_READ
   , NULL
   , CREATE_ALWAYS
   , 0
   , NULL
   );
  if( hFile == INVALID_HANDLE_VALUE )
  {
   ASSERT(FALSE);
   return FALSE;
  }

  DWORD dwWritten = 0;
  ::WriteFile( hFile, pOutput, (UINT)ullSize.QuadPart, &dwWritten, NULL);
  ::FlushFileBuffers(hFile);
  ::CloseHandle(hFile);

  ::GlobalUnlock(hGlobal);

  return TRUE;
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :SelectSingleNode
 // Parameter(s)     :LPCTSTR strPath
 // Return           :CXmlNodePtr
 // Memo             :Query node by XPath
 //-------------------------------------------------------------------------
 CXmlNodePtr CXml::SelectSingleNode(LPCTSTR lpszPath)
 {
  ASSERT( m_pDoc != NULL );

  CXmlNodePtr pNode ( new CXmlNode() );

  if( !GetRoot()->IsNull() )
   (*pNode) = GetRoot()->SelectSingleNode(lpszPath);
  
  return pNode;
 }

 //-------------------------------------------------------------------------
 // Function Name    :SelectNodes
 // Parameter(s)     :LPCTSTR strPath 
 // Return           :CXmlNodesPtr
 // Memo             :Query nodes by XPath
 //-------------------------------------------------------------------------
 CXmlNodesPtr CXml::SelectNodes(LPCTSTR lpszPath)
 {
  ASSERT( m_pDoc != NULL );

  CXmlNodesPtr pNodes( new CXmlNodes() );

  if( !GetRoot()->IsNull() )
   (*pNodes) = GetRoot()->SelectNodes(lpszPath);

  return pNodes;
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :EncodeBase64
 // Parameter(s)     :LPBYTE *pBuf The binary buffer
 //     :ULONG ulSize size
 // Return           :CString  the result
 // Memo             :encoding the binary buffer into Base64 string
 //-------------------------------------------------------------------------
 CString CXml::Base64Encode(LPBYTE pBuf, ULONG ulSize)
 {
  ASSERT( m_pDoc != NULL );
  ASSERT( pBuf != NULL );
  
  CString strRet = _T("");
  try
  {
   MSXML2::IXMLDOMElementPtr pElement = NULL;
   pElement = m_pDoc->createElement( _bstr_t(_T("Base64")) );
   ASSERT( pElement != NULL );

   HRESULT hr = S_OK;
   hr = pElement->put_dataType( _bstr_t(_T("bin.base64")) );
   ASSERT( SUCCEEDED(hr) );

   SAFEARRAY * pAry = SafeArrayCreateVector( VT_UI1, 0L, ulSize);
   ::memcpy( pAry->pvData, pBuf, ulSize);

   VARIANT var;
   VariantInit(&var);
   var.parray = pAry;
   var.vt = VT_ARRAY | VT_UI1;
   pElement->nodeTypedValue = var;

   BSTR bstr = NULL;
   hr = pElement->get_text( &bstr );
   ASSERT( SUCCEEDED(hr) ); 
   strRet = (LPCTSTR)_bstr_t( bstr, true);

   if( bstr != NULL )
   {
    SysFreeString(bstr);
    bstr = NULL;
   }

   RELEASE_PTR(pElement);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXml::Base64Encode failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }

  return strRet;
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :Base64Decode
 // Parameter(s)     :CString strIn  The base64 string
 //     :LPBYTE pBuf  The output buffer
 //     :ULONG * ulSize  the site of buffer
 // Return           :BOOL
 // Memo             :Decode the base64 string into buffer
 //     :NOTE: If the pBuf equal to NULL, then the lSize is the buffer length
 //     :Please see demo
 //-------------------------------------------------------------------------
 BOOL CXml::Base64Decode(CString strIn IN, LPBYTE pBuf IN OUT, LONG & lSize IN OUT)
 {
  ASSERT( m_pDoc != NULL );
  
  try
  {
   MSXML2::IXMLDOMElementPtr pElement = NULL;
   pElement = m_pDoc->createElement( _bstr_t(_T("Base64")) );
   ASSERT( pElement != NULL );

   HRESULT hr = S_OK;
   hr = pElement->put_dataType( _bstr_t(_T("bin.base64")) );
   ASSERT( SUCCEEDED(hr) );

   hr = pElement->put_text( _bstr_t(strIn) );
   ASSERT( SUCCEEDED(hr) );

   hr = SafeArrayGetUBound( pElement->nodeTypedValue.parray, 1, &lSize);
   ASSERT( SUCCEEDED(hr) );
   lSize ++;
   if( pBuf )
   {
    memset( pBuf, 0, lSize);

    memcpy( pBuf, LPVOID(pElement->nodeTypedValue.parray->pvData), lSize); 
   }  

   RELEASE_PTR(pElement);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXml::Base64Decode failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
   return FALSE;
  }
  
  return TRUE;
 }

 //-------------------------------------------------------------------------
 // Function Name    :GetVersion
 // Parameter(s)     :void
 // Return           :MSXML_VERSION
 // Create   :2008-1-16 15:05 Jerry.Wang
 // Memo             :Get the version of current MSXML
 //-------------------------------------------------------------------------
 MSXML_VERSION CXml::GetVersion(void) const
 {
  return m_emVersion;
 }

 //add by fjm 20110927
 //获取xml串
 CString CXml::GetXml() const
 {
  ASSERT( NULL != m_pDoc );
 
  CString strRet = _T("");
  try
  {
   if( NULL != m_pDoc )
   {
    HRESULT hr = S_OK;
    BSTR bstr = NULL;
    hr = m_pDoc->get_xml(&bstr);
 
    ASSERT( SUCCEEDED(hr) ); 
    strRet = (LPCTSTR)_bstr_t(bstr, true);
 
    if( bstr != NULL )
    {
     SysFreeString(bstr);
     bstr = NULL;
    }
   }
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXml::GetXml failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
  return strRet;
 }
 //设置异步
 void CXml::SetSync(BOOL ifSync)
 {
  if (ifSync)
   m_pDoc->async = VARIANT_TRUE;
  else
   m_pDoc->async = VARIANT_FALSE;
 }

}

==================================================.h========================================================

#pragma once


#import "msxml3.dll"   // msxml3.dll or msxml4.dll or msxml5.dll or msxml6.dll
#include

#ifndef ASSERT
#define ASSERT ATLASSERT
#endif

#ifndef TRACE
#define TRACE ATLTRACE
#endif


namespace MSXML2
{
 struct __declspec(uuid("f6d90f11-9c73-11d3-b32e-00c04f990bb4"))
  DOMDocument;

 struct __declspec(uuid("f5078f1b-c551-11d3-89b9-0000f81fe221"))
  DOMDocument26;

 struct __declspec(uuid("f5078f32-c551-11d3-89b9-0000f81fe221"))
  DOMDocument30;

 struct __declspec(uuid("88d969c0-f192-11d4-a65f-0040963251e5"))
  DOMDocument40;

 struct __declspec(uuid("88d969e5-f192-11d4-a65f-0040963251e5"))
  DOMDocument50;

 struct __declspec(uuid("88d96a05-f192-11d4-a65f-0040963251e5"))
  DOMDocument60;
}

 


#ifndef RELEASE_PTR
#define RELEASE_PTR(x) \
 if( x != NULL )  \
  {    \
  x.Release(); \
  x = NULL;  \
  }
#endif


namespace JWXml
{
 class CXml;
 class CXmlNode;
 class CXmlNodes;

#ifdef _HAS_TR1
 typedef std::tr1::shared_ptr  CXmlNodePtr;
 typedef std::tr1::shared_ptr  CXmlNodesPtr;
#else
 typedef std::auto_ptr  CXmlNodePtr;
 typedef std::auto_ptr  CXmlNodesPtr;
#endif

 
}

#include ".\XmlNodes.h"

namespace JWXml
{
 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:

  //   _____________
  //______| constructor |___________________________________________________________________
  CXmlNode(void);
  CXmlNode(const CXmlNode & refNode IN);
  CXmlNode(const CXmlNodePtr pNode IN);
  ~CXmlNode(void);

  //   _______________
  //______| override = |___________________________________________________________________
  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


  //   _______________
  //______|Parent - Child |___________________________________________________________________
  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);

 

  //   _______________
  //______| attribute |___________________________________________________________________
  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 );


  //   _______
  //______| value |___________________________________________________________________ 
  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);

  //   _______________________
  //______| InnerXml OuterXml |___________________________________________________________________
  CString GetOuterXml(void) const;
  CString GetInnerXml(void) const;

 };
}

===========.cpp====

#include "StdAfx.h"
#include "./xmlnode.h"


namespace JWXml
{

 //-------------------------------------------------------------------------
 // Function Name    :_GetValue
 // Parameter(s)     :CString & strValue OUT value
 // Return           :BOOL     false means failed
 // Memo             :get the text value of the current node
 //     :NOTE: the node should not contain children if u invoke this method
 //-------------------------------------------------------------------------
 BOOL CXmlNode::_GetValue(CString & strValue OUT) const
 {
  ASSERT( !IsNull() );

  HRESULT hr = S_OK;
  try
  {
   BSTR bstr = NULL;
   hr = m_pNode->get_text( &bstr );
   ASSERT( SUCCEEDED(hr) ); 
   strValue = (LPCTSTR)_bstr_t( bstr, true);

   if( bstr != NULL )
   {
    SysFreeString(bstr);
    bstr = NULL;
   }
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::_GetValue failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
   return FALSE;
  }
  
  return SUCCEEDED(hr);
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :_SetValue
 // Parameter(s)     :CString & strValue IN
 // Return           :BOOL     false means failed
 // Memo             :Set the text value of the current node
 //-------------------------------------------------------------------------
 BOOL CXmlNode:: _SetValue(CString & strValue IN) const
 {
  ASSERT( !IsNull() );

  HRESULT hr = S_OK;

  try
  {
   hr = m_pNode->put_text( _bstr_t(strValue) );
   ASSERT( SUCCEEDED(hr) );
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::_SetValue failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
   return FALSE;
  }
  return SUCCEEDED(hr);
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :_GetAttribute
 // Parameter(s)     :CString & strName IN 
 // Return   :CString & strValue OUT 
 // Memo             :Get the attribute value
 //-------------------------------------------------------------------------
 BOOL CXmlNode::_GetAttribute( CString & strName IN, CString & strValue OUT) const
 {
  if( m_pNode == NULL )
  {
   ASSERT(FALSE);
   return FALSE;
  }

  HRESULT hr = S_OK;

  try
  {
   MSXML2::IXMLDOMNamedNodeMapPtr pIXMLDOMNamedNodeMap = NULL;
   hr = m_pNode->get_attributes(&pIXMLDOMNamedNodeMap);
   if( !SUCCEEDED(hr) )
   {
    ASSERT( FALSE );
    return FALSE;
   }

   MSXML2::IXMLDOMNodePtr pIXMLDOMNode = NULL;
   pIXMLDOMNode = pIXMLDOMNamedNodeMap->getNamedItem( _bstr_t(strName) );

   if( pIXMLDOMNode == NULL )
   {
    strValue.Empty();
   }
   else
   {
    VARIANT varValue;
    hr = pIXMLDOMNode->get_nodeValue(&varValue);
    if( !SUCCEEDED(hr) )
    {
     ASSERT( FALSE );
     return FALSE;
    }

    strValue = (LPCTSTR)(_bstr_t)varValue;
   }

   RELEASE_PTR(pIXMLDOMNode);
   RELEASE_PTR(pIXMLDOMNamedNodeMap);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::_GetAttribute failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
   return FALSE;
  }

  return TRUE;
 }


 //-------------------------------------------------------------------------
 // Function Name    :_SetAttribute
 // Parameter(s)     :CString & strName IN 
 //     :CString & strValue IN 
 // Return           :BOOL
 // Memo             :Set the attribute value
 //-------------------------------------------------------------------------
 BOOL CXmlNode::_SetAttribute( CString & strName IN
        , CString & strValue IN
        , CString & strPrefix IN
        , CString & strNamespaceURI IN
        ) const
 {
  if( m_pNode == NULL )
  {
   ASSERT(FALSE);
   return FALSE;
  }

  HRESULT hr = S_OK;
  try
  {
   MSXML2::IXMLDOMDocumentPtr pDoc = NULL;
   hr = m_pNode->get_ownerDocument(&pDoc);
   ASSERT( SUCCEEDED(hr) );
   
   CString strFullName;
   strFullName.Format( strPrefix.IsEmpty() ? _T("%s%s") : _T("%s:%s"), strPrefix, strName);
   
   MSXML2::IXMLDOMAttributePtr pAttribute = NULL;
   pAttribute = pDoc->createNode( _variant_t(_T("attribute")), _bstr_t(strFullName), _bstr_t(strNamespaceURI) );
   pAttribute->Putvalue(_variant_t(strValue));
   ASSERT( pAttribute != NULL );
   
   MSXML2::IXMLDOMElementPtr pElement = static_cast (m_pNode);
   hr = pElement->setAttributeNode(pAttribute);
   RELEASE_PTR(pAttribute);
   RELEASE_PTR(pElement);
   RELEASE_PTR(pDoc);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::_SetAttribute failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
   return FALSE;
  }

  return SUCCEEDED(hr);
 }

 

 

 //-------------------------------------------------------------------------
 // Function Name    :CXmlNode
 // Parameter(s)     :MSXML2::IXMLDOMNodePtr pNode [in]
 // Memo             :constructor
 //-------------------------------------------------------------------------
 CXmlNode::CXmlNode( MSXML2::IXMLDOMNodePtr pNode IN)
 {
  m_pNode = pNode;
 }


 //-------------------------------------------------------------------------
 // Function Name    :CXmlNode
 // Parameter(s)     :void
 // Memo             :constructor
 //-------------------------------------------------------------------------
 CXmlNode::CXmlNode(void)
 {
  m_pNode = NULL; 
 }


 //-------------------------------------------------------------------------
 // Function Name    :CXmlNode
 // Parameter(s)     :CXmlNode & refNode [in]
 // Memo             :constructor
 //-------------------------------------------------------------------------
 CXmlNode::CXmlNode( const CXmlNode & refNode IN)
 {
  m_pNode = refNode.m_pNode;
 }

 //-------------------------------------------------------------------------
 // Function Name    :CXmlNode
 // Parameter(s)     :CXmlNode & refNode [in]
 // Memo             :constructor
 //-------------------------------------------------------------------------
 CXmlNode::CXmlNode( const CXmlNodePtr pNode IN)
 {
  m_pNode = pNode->m_pNode;
 }

 //-------------------------------------------------------------------------
 // Function Name    :~CXmlNode
 // Parameter(s)     :void
 // Memo             :destructor
 //-------------------------------------------------------------------------
 CXmlNode::~CXmlNode(void)
 {
  RELEASE_PTR(m_pNode);
 }


 //-------------------------------------------------------------------------
 // Function Name    :Release
 // Parameter(s)     :void
 // Return           :void
 // Memo             :release the node
 //-------------------------------------------------------------------------
 void CXmlNode::Release(void)
 {
  RELEASE_PTR(m_pNode);
 }

 


 //-------------------------------------------------------------------------
 // Function Name    :operator =
 // Parameter(s)     :CXmlNodePtr pNode [in]
 // Return           :CXmlNodePtr
 // Memo             :override the =
 //-------------------------------------------------------------------------
 CXmlNodePtr CXmlNode::operator = (CXmlNodePtr pNode IN)
 {
  RELEASE_PTR(m_pNode);

  m_pNode = pNode->m_pNode;
  return pNode;
 }


 //-------------------------------------------------------------------------
 // Function Name    :operator =
 // Parameter(s)     :CXmlNode & refNode [in]
 // Return           :CXmlNode &
 // Memo             :override the =
 //-------------------------------------------------------------------------
 CXmlNode & CXmlNode::operator = (const CXmlNode & refNode IN)
 {
  RELEASE_PTR(m_pNode);

  m_pNode = refNode.m_pNode;
  return (*this);
 }


 //-------------------------------------------------------------------------
 // Function Name    :IsNull
 // Parameter(s)     :void
 // Return           :BOOL
 // Memo             :Whether this node exist
 //-------------------------------------------------------------------------
 BOOL CXmlNode::IsNull(void) const
 {
  return m_pNode == NULL;
 }

 //-------------------------------------------------------------------------
 // Function Name    :GetChild
 // Parameter(s)     :CString strName  节点名称
 //     :BOOL bBuildIfNotExist true: create if the node not exist
 // Return           :The child node pointer
 // Memo             :get the child
 //-------------------------------------------------------------------------
 CXmlNodePtr CXmlNode::GetChild( CString strName, BOOL bBuildIfNotExist /* = TRUE */)
 {
  ASSERT( m_pNode != NULL );

  CXmlNodePtr pChild( new CXmlNode() );

  try
  {
   MSXML2::IXMLDOMNodePtr pChildNode = NULL;
   CString strXPath;
   strName.Replace( _T("'"), _T("''"));
   strXPath.Format( _T("*[local-name(.) = '%s']"), strName);
   pChildNode = m_pNode->selectSingleNode(_bstr_t((LPCTSTR)strXPath));

   // create if not exist
   if( pChildNode == NULL && bBuildIfNotExist )
   {
    MSXML2::IXMLDOMDocumentPtr pDoc = NULL;
    HRESULT hr = m_pNode->get_ownerDocument(&pDoc);
    ASSERT( SUCCEEDED(hr) );

    pChildNode = pDoc->createElement( _bstr_t(strName) );
    ASSERT( pChildNode != NULL );

    m_pNode->appendChild(pChildNode);

    RELEASE_PTR(pDoc);
   }

   pChild->m_pNode = pChildNode; 
   RELEASE_PTR(pChildNode);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::GetChild failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }

  return pChild;
 }


 //-------------------------------------------------------------------------
 // Function Name    :NewChild
 // Parameter(s)     :CString strName the node name
 // Return           :CXmlNodePtr
 // Memo             :create new child
 //-------------------------------------------------------------------------
 CXmlNodePtr CXmlNode::NewChild( CString strName )
 {
  ASSERT( m_pNode != NULL );

  CXmlNodePtr pChild( new CXmlNode() );

  try
  {
   MSXML2::IXMLDOMDocumentPtr pDoc = NULL;
   HRESULT hr = m_pNode->get_ownerDocument(&pDoc);
   ASSERT( SUCCEEDED(hr) );

   MSXML2::IXMLDOMNodePtr pChildNode = NULL;
   pChildNode = pDoc->createElement( _bstr_t(strName) );
   ASSERT( pChildNode != NULL );
   RELEASE_PTR(pDoc);

   m_pNode->appendChild(pChildNode);
   pChild->m_pNode = pChildNode;
   RELEASE_PTR(pChildNode);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::NewChild failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
  return pChild; 
 }


 //-------------------------------------------------------------------------
 // Function Name    :AttachChild
 // Parameter(s)     :CXmlNodePtr & pChildNode
 // Return           :void
 // Memo             :Attach a new child
 //-------------------------------------------------------------------------
 void CXmlNode::AttachChild( CXmlNodePtr & pChildNode)
 {
  ASSERT( m_pNode != NULL );

  try
  {
   m_pNode->appendChild( pChildNode->m_pNode );
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::AttachChild failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
 }


 //-------------------------------------------------------------------------
 // Function Name    :AttachChild
 // Parameter(s)     :CXmlNode & refChildNode
 // Return           :void
 // Memo             :Attach a new child
 //-------------------------------------------------------------------------
 void CXmlNode::AttachChild( CXmlNode & refChildNode)
 {
  ASSERT( m_pNode != NULL );

  try
  {
   m_pNode->appendChild( refChildNode.m_pNode );
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::AttachChild failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
 }


 //-------------------------------------------------------------------------
 // Function Name    :GetParent
 // Parameter(s)     :void
 // Return           :CXmlNodePtr
 // Memo             :get the parent node
 //-------------------------------------------------------------------------
 CXmlNodePtr CXmlNode::GetParent(void)
 {
  ASSERT( m_pNode != NULL );

  CXmlNodePtr pParent( new CXmlNode() );

  try
  {
   pParent->m_pNode = m_pNode->GetparentNode();
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::GetParent failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
  return pParent;
 }

 


 //-------------------------------------------------------------------------
 // Function Name    :GetName
 // Parameter(s)     :void
 // Return           :CString
 // Memo             :get the name of the current node
 //-------------------------------------------------------------------------
 CString CXmlNode::GetName(void) const
 {
  ASSERT( m_pNode != NULL );

  CString strRet;

  try
  {
   BSTR bstr = NULL;
   HRESULT hr = m_pNode->get_nodeName(&bstr);
   ASSERT( SUCCEEDED(hr) ); 
   strRet = (LPCTSTR)_bstr_t( bstr, true);

   if( bstr != NULL )
   {
    SysFreeString(bstr);
    bstr = NULL;
   }
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::GetName failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }

  return strRet;
 }


 //-------------------------------------------------------------------------
 // Function Name    :RemoveAttribute
 // Parameter(s)     :CString strName IN 属性名称
 // Return           :BOOL
 // Memo             :remove attribute
 //-------------------------------------------------------------------------
 BOOL CXmlNode::RemoveAttribute( CString strName IN )
 {
  ASSERT( m_pNode != NULL );

  HRESULT hr = S_OK;

  try
  {
   MSXML2::IXMLDOMNamedNodeMapPtr pIXMLDOMNamedNodeMap = NULL;
   hr = m_pNode->get_attributes(&pIXMLDOMNamedNodeMap);
   ASSERT( SUCCEEDED(hr) );

   if( SUCCEEDED(hr) )
    pIXMLDOMNamedNodeMap->removeNamedItem( _bstr_t(strName) );
   ASSERT( SUCCEEDED(hr) );

   RELEASE_PTR(pIXMLDOMNamedNodeMap);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::RemoveAttribute failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
   return FALSE;
  }

  
  return SUCCEEDED(hr);
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :HasChildren
 // Parameter(s)     :void
 // Return           :BOOL
 // Memo             :whether the node has children
 //-------------------------------------------------------------------------
 BOOL CXmlNode::HasChildren(void)
 {
  ASSERT( m_pNode != NULL );

  BOOL bHasChildren = FALSE;
  try
  {
   MSXML2::IXMLDOMNodeListPtr pNodeList = NULL;
   pNodeList = m_pNode->selectNodes( _bstr_t(_T("child::*")) );
   ASSERT( pNodeList != NULL );

   bHasChildren = pNodeList->length > 0;
   RELEASE_PTR(pNodeList);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::HasChildren failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
  return bHasChildren;
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :Detach
 // Parameter(s)     :
 // Return           :
 // Memo             :detach the current node from parent
 //-------------------------------------------------------------------------
 CXmlNode & CXmlNode::Detach(void)
 {
  ASSERT( m_pNode != NULL );

  try
  {
   HRESULT hr = S_OK;
   MSXML2::IXMLDOMNodePtr pNode = NULL;
   hr = m_pNode->get_parentNode(&pNode);
   ASSERT( SUCCEEDED(hr) );

   pNode->removeChild(m_pNode);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::Detach failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
  return (*this);
 }

 //-------------------------------------------------------------------------
 // Function Name    :RemoveChildren
 // Parameter(s)     :
 // Return           :BOOL
 // Memo             :remove all children
 //-------------------------------------------------------------------------
 BOOL CXmlNode::RemoveChildren(void)
 {
  ASSERT( m_pNode != NULL );

  try
  {
   MSXML2::IXMLDOMNodeListPtr pNodeList = m_pNode->childNodes;

   for( int i = pNodeList->length - 1; i >= 0; i--)
   {
    m_pNode->removeChild( pNodeList->item[i] );
   }

   RELEASE_PTR(pNodeList);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::Remove failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
   return FALSE;
  }

  return TRUE;
 }


 //-------------------------------------------------------------------------
 // Function Name    :GetChildren
 // Parameter(s)     :void
 // Return           :CXmlNodesPtr
 // Memo             :get all children nodes
 //-------------------------------------------------------------------------
 CXmlNodesPtr CXmlNode::GetChildren()
 {
  ASSERT( m_pNode != NULL );

  CXmlNodesPtr pNodes ( new CXmlNodes() );
  try
  {
   MSXML2::IXMLDOMNodeListPtr pNodeList = NULL;
   pNodeList = m_pNode->selectNodes(_bstr_t(_T("child::*")));

   pNodes->m_pNodeList = pNodeList;
   RELEASE_PTR(pNodeList);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::GetChildren failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
  return pNodes;
 }

 


 //-------------------------------------------------------------------------
 // Function Name    :SelectSingleNode
 // Parameter(s)     :LPCTSTR lpszPath  XPATH
 // Return           :CXmlNodePtr
 // Memo             :XPath selectSingleNode
 //-------------------------------------------------------------------------
 CXmlNodePtr CXmlNode::SelectSingleNode(LPCTSTR lpszPath)
 {
  ASSERT( m_pNode != NULL );

  CXmlNodePtr pNode ( new CXmlNode() );

  try
  {
   MSXML2::IXMLDOMNodePtr pItem = NULL;
   pItem = m_pNode->selectSingleNode( _bstr_t(lpszPath) );

   pNode->m_pNode = pItem;
   RELEASE_PTR(pItem);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::SelectSingleNode( %s ) failed:%s\n"), lpszPath, e.ErrorMessage());
   ASSERT( FALSE );
  }

  return pNode;
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :SelectNodes
 // Parameter(s)     :LPCTSTR lpszPath  XPATH
 // Return           :CXmlNodesPtr
 // Memo             :XPath selectNodes
 //-------------------------------------------------------------------------
 CXmlNodesPtr CXmlNode::SelectNodes(LPCTSTR lpszPath)
 {
  ASSERT( m_pNode != NULL );

  CXmlNodesPtr pNodes ( new CXmlNodes() );
  try
  {
   MSXML2::IXMLDOMNodeListPtr pNodeList = NULL;
   pNodeList = m_pNode->selectNodes( _bstr_t(lpszPath) );

   pNodes->m_pNodeList = pNodeList;
   RELEASE_PTR(pNodeList);
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::SelectNodes failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }

  return pNodes;
 }

 


 //////////////////////////////////////////////////////////////////////////
 // the following methods are getting value

 // get CString value
 CString CXmlNode::GetValue(LPCTSTR lpszValue /* = NULL */ ) const
 {
  CString strValue;
  _GetValue(strValue);

  if( strValue.IsEmpty() &&
   lpszValue != NULL )
  {
   strValue = lpszValue;
   _SetValue(strValue);
  }

  return strValue;
 }

 // get bool value
 bool CXmlNode::GetValue( bool bDefault ) const
 {
  CString strValue;
  _GetValue(strValue);

  if( strValue.CompareNoCase(_T("1")) == 0 )
  {
   return true;
  }
  else if( strValue.CompareNoCase(_T("0")) == 0 )
  {
   return false;
  }
  else
  {
   strValue = bDefault ? "1" : "0";
   _SetValue(strValue);
   return bDefault;
  } 
 }

 // get int value
 int CXmlNode::GetValue( int nDefault ) const
 {
  CString strValue;
  _GetValue(strValue);

  if( strValue.IsEmpty() )
  {
   strValue.Format( _T("%d"), nDefault);
   _SetValue(strValue);
  }

  return _ttoi(strValue);
 }

 // get long value
 long CXmlNode::GetValue( long lDefault ) const
 {
  CString strValue;
  _GetValue(strValue);

  if( strValue.IsEmpty() )
  {
   strValue.Format( _T("%ld"), lDefault);
   _SetValue(strValue);
  }

  return _ttol(strValue);
 }

 // get __int64 value
 __int64 CXmlNode::GetValue( __int64 llDefault ) const
 {
  CString strValue;
  _GetValue(strValue);

  if( strValue.IsEmpty() )
  {
   strValue.Format( _T("%I64d"), llDefault);
   _SetValue(strValue);
  }

  return _ttoi64(strValue);
 }

 // get float value
 float CXmlNode::GetValue( float fDefault ) const
 {
  CString strValue;
  _GetValue(strValue);

  if( strValue.IsEmpty() )
  {
   strValue.Format( _T("%f"), fDefault);
   _SetValue(strValue);
  }

  return static_cast (_tstof(strValue));
//  return static_cast (atof(strValue.GetBuffer(0)));
 }

 // get double value
 double CXmlNode::GetValue( double dDefault ) const
 {
  CString strValue;
  _GetValue(strValue);

  if( strValue.IsEmpty() )
  {
   strValue.Format( _T("%e"), dDefault);
   _SetValue(strValue);
  }

  return _tstof(strValue);
//  return atof(strValue);
 }

 // get DWORD value
 DWORD CXmlNode::GetValue( DWORD dwDefault ) const
 {
  CString strValue;
  _GetValue(strValue);

  if( strValue.IsEmpty() )
  {
   strValue.Format( _T("%lu"), dwDefault);
   _SetValue(strValue);
  }

  return _tcstoul(strValue, NULL, 10);
 }


 //////////////////////////////////////////////////////////////////////////
 // the following methods are setting value

 // set LPCTSTR value
 BOOL CXmlNode::SetValue( LPCTSTR lpszValue )
 {
  CString strValue(lpszValue);
  return _SetValue(strValue);
 }

 // set bool value
 BOOL CXmlNode::SetValue( bool bValue )
 {
  CString strValue;
  strValue = bValue ? _T("1") : _T("0");

  return _SetValue(strValue);
 }

 // set int value
 BOOL CXmlNode::SetValue( int nValue )
 {
  CString strValue;
  strValue.Format( _T("%d"), nValue);

  return _SetValue(strValue);
 }

 // set long value
 BOOL CXmlNode::SetValue( long lValue )
 {
  CString strValue;
  strValue.Format( _T("%ld"), lValue);

  return _SetValue(strValue);
 }

 // set __int64 value
 BOOL CXmlNode::SetValue( __int64 llValue )
 {
  CString strValue;
  strValue.Format( _T("%I64d"), llValue);

  return _SetValue(strValue);
 }


 // set float value
 BOOL CXmlNode::SetValue( float fValue )
 {
  CString strValue;
  strValue.Format( _T("%f"), fValue);

  return _SetValue(strValue);
 }

 // set double value
 BOOL CXmlNode::SetValue( double dValue )
 {
  CString strValue;
  strValue.Format( _T("%e"), dValue);

  return _SetValue(strValue);
 }

 // set DWORD value
 BOOL CXmlNode::SetValue( DWORD dwValue )
 {
  CString strValue;
  strValue.Format( _T("%lu"), dwValue);

  return _SetValue(strValue);
 }


 //////////////////////////////////////////////////////////////////////////
 // The following methods are getting attribute

 // get LPCTSTR attribute
 CString CXmlNode::GetAttribute( CString strName, LPCTSTR lpszDefault /* = NULL */) const
 {
  CString strValue;
  _GetAttribute( strName, strValue);

  if( strValue.IsEmpty() &&
   lpszDefault != NULL )
  {
   strValue = lpszDefault;
  }
  return strValue;
 }

 // get bool attribute
 bool CXmlNode::GetAttribute( CString strName, bool bDefault) const
 {
  CString strValue;
  _GetAttribute( strName, strValue);

  if( strValue.CompareNoCase(_T("1")) == 0 )
  {
   return true;
  }
  else if( strValue.CompareNoCase(_T("0")) == 0 )
  {
   return false;
  }
  else
  {
   return bDefault;
  } 
 }

 // get int attribute
 int CXmlNode::GetAttribute( CString strName, int nDefault) const
 {
  CString strValue;
  _GetAttribute( strName, strValue);

  if( strValue.IsEmpty() )
   strValue.Format( _T("%d"), nDefault);

  return _ttoi(strValue);
 }


 // get long attribute
 long CXmlNode::GetAttribute( CString strName, long lDefault) const
 {
  CString strValue;
  _GetAttribute( strName, strValue);

  if( strValue.IsEmpty() )
   strValue.Format( _T("%ld"), lDefault);

  return _ttol(strValue);
 }

 // get __int64 attribute
 __int64 CXmlNode::GetAttribute( CString strName, __int64 llDefault) const
 {
  CString strValue;
  _GetAttribute( strName, strValue);

  if( strValue.IsEmpty() )
   strValue.Format( _T("%I64d"), llDefault);

  return _ttoi64(strValue);
 }


 // get float attribute
 float CXmlNode::GetAttribute( CString strName, float fDefault) const
 {
  CString strValue;
  _GetAttribute( strName, strValue);

  if( strValue.IsEmpty() )
   strValue.Format( _T("%f"), fDefault);

  return static_cast (_tstof(strValue));
//  return static_cast (atof(strValue));
 }

 // get double attribute
 double CXmlNode::GetAttribute( CString strName, double dDefault) const
 {
  CString strValue;
  _GetAttribute( strName, strValue);

  if( strValue.IsEmpty() )
   strValue.Format( _T("%e"), dDefault);

  return _tstof(strValue);
//  return atof(strValue);
 }

 // get DWORD attribute
 DWORD CXmlNode::GetAttribute( CString strName, DWORD dwDefault) const
 {
  CString strValue;
  _GetAttribute( strName, strValue);

  if( strValue.IsEmpty() )
   strValue.Format( _T("%lu"), dwDefault);

  return _tcstoul(strValue, NULL, 10);
 }


 //////////////////////////////////////////////////////////////////////////
 // The following methods are setting attribute

 // set LPCTSTR attribute
 BOOL CXmlNode::SetAttribute( CString strName
  , LPCTSTR lpszValue
  , CString strPrefix /* = _T("") */
  , CString strNamespaceURI /* = _T("") */
  )
 {
  CString strValue;
  strValue = lpszValue;

  return _SetAttribute( strName, strValue, strPrefix, strNamespaceURI); 
 }

 // set bool attribute
 BOOL CXmlNode::SetAttribute( CString strName
  , bool bValue
  , CString strPrefix /* = _T("") */
  , CString strNamespaceURI /* = _T("") */
  )
 {
  CString strValue;
  strValue = bValue ? _T("1") : _T("0");

  return _SetAttribute( strName, strValue, strPrefix, strNamespaceURI);
 }

 // set int attribute
 BOOL CXmlNode::SetAttribute( CString strName
  , int nValue
  , CString strPrefix /* = _T("") */
  , CString strNamespaceURI /* = _T("") */
  )
 {
  CString strValue;
  strValue.Format( _T("%d"), nValue);

  return _SetAttribute( strName, strValue, strPrefix, strNamespaceURI);
 }

 // set long attribute
 BOOL CXmlNode::SetAttribute( CString strName
  , long lValue
  , CString strPrefix /* = _T("") */
  , CString strNamespaceURI /* = _T("") */
  )
 {
  CString strValue;
  strValue.Format( _T("%ld"), lValue);

  return _SetAttribute( strName, strValue, strPrefix, strNamespaceURI);
 }

 // set __int64 attribute
 BOOL CXmlNode::SetAttribute( CString strName
  , __int64 llValue
  , CString strPrefix /* = _T("") */
  , CString strNamespaceURI /* = _T("") */
  )
 {
  CString strValue;
  strValue.Format( _T("%I64d"), llValue);

  return _SetAttribute( strName, strValue, strPrefix, strNamespaceURI);
 }


 // set float attribute
 BOOL CXmlNode::SetAttribute( CString strName
  , float fValue
  , CString strPrefix /* = _T("") */
  , CString strNamespaceURI /* = _T("") */
  )
 {
  CString strValue;
  strValue.Format( _T("%f"), fValue);

  return _SetAttribute( strName, strValue, strPrefix, strNamespaceURI);
 }

 // set double attribute
 BOOL CXmlNode::SetAttribute( CString strName
  , double dValue
  , CString strPrefix /* = _T("") */
  , CString strNamespaceURI /* = _T("") */
  )
 {
  CString strValue;
  strValue.Format( _T("%e"), dValue);

  return _SetAttribute( strName, strValue, strPrefix, strNamespaceURI);
 }

 // set DWORD attribute
 BOOL CXmlNode::SetAttribute( CString strName
  , DWORD dwValue
  , CString strPrefix /* = _T("") */
  , CString strNamespaceURI /* = _T("") */
  )
 {
  CString strValue;
  strValue.Format( _T("%lu"), dwValue);

  return _SetAttribute( strName, strValue, strPrefix, strNamespaceURI);
 }

 //-------------------------------------------------------------------------
 // Function Name    :GetOuterHTML
 // Parameter(s)     :void
 // Return           :CString
 // Create   :2008-1-14 11:04 王嘉
 // Memo             :Get OuterXml
 //-------------------------------------------------------------------------
 CString CXmlNode::GetOuterXml(void) const
 {
  ASSERT(!IsNull());

  CString strRet = _T("");
  try
  {
   if( !IsNull() )
   {
    HRESULT hr = S_OK;
    BSTR bstr = NULL;
    hr = m_pNode->get_xml(&bstr);

    ASSERT( SUCCEEDED(hr) ); 
    strRet = (LPCTSTR)_bstr_t( bstr, true);

    if( bstr != NULL )
    {
     SysFreeString(bstr);
     bstr = NULL;
    }
   }
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNode::GetOuterXml failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }
  return strRet;
 }// GetOuterXml


 //-------------------------------------------------------------------------
 // Function Name    :GetInnerXml
 // Parameter(s)     :void
 // Return           :CString
 // Create   :2008-1-14 11:37 王嘉
 // Memo             :get InnerXml
 //-------------------------------------------------------------------------
 CString CXmlNode::GetInnerXml(void) const
 {
  ASSERT(!IsNull());

  CString strRet = GetOuterXml();
  int nFirst = strRet.Find('>');
  int nEnd = strRet.ReverseFind('<');
  if( nFirst > 0 && nEnd > 0 && nEnd > nFirst )
   strRet = strRet.Mid( nFirst + 1, nEnd - nFirst - 1);
  return strRet;
 }// GetOuterXml

}

=======================================================.h=============================================

#pragma once

#include "./XmlNode.h"

namespace JWXml
{
 class CXmlNodes
 {
  friend class CXml;
  friend class CXmlNode;
  friend class CXmlNodes;

 public:
  //    ____________
  //__________| constuctor |______________________________________
  ~CXmlNodes(void);
  CXmlNodes(void);
  CXmlNodes( const CXmlNodes & refNodes );
  CXmlNodes( CXmlNodesPtr pNodes );

  //    __________
  //__________| override |______________________________________
  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;

 };
}

=========.cpp==========

#include "StdAfx.h"
#include "./XmlNodes.h"


namespace JWXml
{


 // constructors
 CXmlNodes::CXmlNodes(MSXML2::IXMLDOMNodeListPtr pNodeList)
 {
  m_pNodeList = pNodeList;
 }

 CXmlNodes::CXmlNodes(const CXmlNodes & refNodes )
 {
  m_pNodeList = refNodes.m_pNodeList;
 }

 CXmlNodes::CXmlNodes( CXmlNodesPtr pNodes )
 {
  m_pNodeList = pNodes->m_pNodeList;
 }

 CXmlNodes::CXmlNodes(void)
 : m_pNodeList(NULL)
 {
 }

 CXmlNodes::~CXmlNodes(void)
 {
  Release();
 }

 //////////////////////////////////////////////////////////////////////////
 void CXmlNodes::Release(void)
 {
  RELEASE_PTR(m_pNodeList);
 }


 //-------------------------------------------------------------------------
 // Function Name    :operator =
 // Parameter(s)     :CXmlNodesPtr pNodes
 // Return           :CXmlNodesPtr
 // Memo             :override the = symbol
 //-------------------------------------------------------------------------
 CXmlNodesPtr CXmlNodes::operator = ( CXmlNodesPtr pNodes IN )
 {
  RELEASE_PTR(m_pNodeList);

  m_pNodeList = pNodes->m_pNodeList;
  return pNodes;
 }


 //-------------------------------------------------------------------------
 // Function Name    :operator =
 // Parameter(s)     :CXmlNodes & refNodes
 // Return           :CXmlNodes &
 // Memo             :override the = symbol
 //-------------------------------------------------------------------------
 CXmlNodes & CXmlNodes::operator = (const CXmlNodes & refNodes)
 {
  RELEASE_PTR(m_pNodeList);

  m_pNodeList = refNodes.m_pNodeList;
  return (*this);
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :GetCount
 // Parameter(s)     :void
 // Return           :LONG
 // Memo             :get the total count of the elements in this list
 //-------------------------------------------------------------------------
 LONG CXmlNodes::GetCount(void)
 {
  ASSERT( m_pNodeList != NULL );

  try
  {
   return m_pNodeList->length;
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNodes::GetCount failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
   return -1;
  }
 }

 

 //-------------------------------------------------------------------------
 // Function Name    :GetItem
 // Parameter(s)     :LONG nIndex The index of the item
 // Return           :CXmlNodePtr
 // Memo             :Get the item in the list
 //-------------------------------------------------------------------------
 CXmlNodePtr CXmlNodes::GetItem( LONG nIndex )
 {
  ASSERT( m_pNodeList != NULL );
  ASSERT( nIndex >= 0 && nIndex < GetCount() );

  CXmlNodePtr pNode ( new CXmlNode(m_pNodeList->item[nIndex]) );

  return pNode;
 }


 //-------------------------------------------------------------------------
 // Function Name    :operator[]
 // Parameter(s)     :INT nIndex
 // Return           :CXmlNodePtr
 // Memo             :override [], get the item in the list by index
 //-------------------------------------------------------------------------
 CXmlNodePtr CXmlNodes::operator[] ( LONG lIndex )
 {
  return GetItem(lIndex);
 }


 //-------------------------------------------------------------------------
 // Function Name    :GetItem
 // Parameter(s)     :LPCTSTR lpszName the child node name
 // Return           :CXmlNodePtr
 // Memo             :get the child node by the node name
 //-------------------------------------------------------------------------
 CXmlNodePtr CXmlNodes::GetItem( LPCTSTR lpszName )
 {
  ASSERT( m_pNodeList != NULL );
  ASSERT( lpszName != NULL );
  
  CXmlNodePtr pNode ( new CXmlNode() );

  try
  {
   HRESULT hr = S_OK;
   CString strName;
   BSTR bstr = NULL;
   MSXML2::IXMLDOMNodePtr pItem = NULL; 

   for( int i = 0; i < m_pNodeList->length; i++)
   {
    pItem = m_pNodeList->item[i];

    hr = pItem->get_nodeName(&bstr);  

    strName = (LPCTSTR)_bstr_t( bstr, true);
    if( bstr != NULL )
    {
     SysFreeString(bstr);
     bstr = NULL;
    }

    // get the first element
    if( strName.Compare(lpszName) == 0 )
    {
     pNode->m_pNode = pItem;
     RELEASE_PTR(pItem);
     return pNode;
    }

    RELEASE_PTR(pItem);
   }
  }
  catch ( _com_error e )
  {
   TRACE( _T("CXmlNodes::GetItem failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
  }

  return pNode;
 }


 //-------------------------------------------------------------------------
 // Function Name    :operator[]
 // Parameter(s)     :LPCTSTR lpszName 
 // Return           :CXmlNodePtr
 // Memo             :override the [], same as GetItem( LPCTSTR lpszName )
 //-------------------------------------------------------------------------
 CXmlNodePtr CXmlNodes::operator[] ( LPCTSTR lpszName )
 {
  return GetItem(lpszName);
 }

}

=================================================.h===============================================

#pragma once
#include "./Xml.h"

 

namespace JWXml
{
 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;
 };
}

==

==========.cpp===============

 

#include "StdAfx.h"
#include "./Xsl.h"

namespace JWXml
{
 CXsl::CXsl(void)
 {
 }

 CXsl::~CXsl(void)
 {
  Close();
 }

 //-------------------------------------------------------------------------
 // Function Name    :Open
 // Parameter(s)     :LPCTSTR lpszXslFilePath XSL file path
 // Return           :BOOL
 // Create   :2008-1-16 16:09 Jerry.Wang
 // Memo             :Open the xsl file
 //-------------------------------------------------------------------------
 BOOL CXsl::Open(LPCTSTR lpszXslFilePath)
 {
  Close();

  HRESULT hr = S_OK;

  try
  {
   hr = m_pIXSLTemplate.CreateInstance( __uuidof(MSXML2::XSLTemplate) );
   if( FAILED(hr) ) { ASSERT(FALSE); return FALSE; }

   hr = m_pStyleSheet.CreateInstance( __uuidof(MSXML2::FreeThreadedDOMDocument) );
   if( FAILED(hr) ) { ASSERT(FALSE); return FALSE; }

   VARIANT_BOOL vbSuccessful = VARIANT_TRUE;
   vbSuccessful = m_pStyleSheet->load( _variant_t(lpszXslFilePath) );
   if( vbSuccessful == VARIANT_FALSE ) { ASSERT(FALSE); return FALSE; }

   hr = m_pIXSLTemplate->putref_stylesheet(m_pStyleSheet);
   if( FAILED(hr) ) { VERIFY(FALSE); return FALSE; }

   m_pIXSLProcessor = m_pIXSLTemplate->createProcessor();
   if( m_pIXSLProcessor == NULL ) { ASSERT(FALSE); return FALSE; }

   return TRUE;
  }
  catch( _com_error e)
  {
   TRACE( _T("CXsl::Open(%s) failed:%s\n"), lpszXslFilePath, e.ErrorMessage());
   ASSERT( FALSE );
   return FALSE;
  }
 }

 //-------------------------------------------------------------------------
 // Function Name    :Close
 // Parameter(s)     :void
 // Return           :void
 // Create   :2008-1-16 16:10 Jerry.Wang
 // Memo             :Close the xsl file
 //-------------------------------------------------------------------------
 void CXsl::Close(void)
 {
  RELEASE_PTR(m_pIXSLTemplate);
  RELEASE_PTR(m_pStyleSheet);
  RELEASE_PTR(m_pIXSLProcessor); 
 }

 //-------------------------------------------------------------------------
 // Function Name    :AddParameter
 // Parameter(s)     :LPCTSTR lpszParamName
 //     :LPCTSTR lpszParamValue
 //     :LPCTSTR lpszNamespaceURI
 // Return           :BOOL
 // Create   :2008-1-18 22:10 Jerry.Wang
 // Memo             :Add a parameter to the XSLT
 //-------------------------------------------------------------------------
 BOOL CXsl::AddParameter( LPCTSTR lpszParamName, LPCTSTR lpszParamValue, LPCTSTR lpszNamespaceURI /* = _T("") */)
 {
  ASSERT(m_pIXSLProcessor != NULL);
  try
  {
   HRESULT hr = m_pIXSLProcessor->addParameter( _bstr_t(lpszParamName)
    , _variant_t(lpszParamValue)
    , _bstr_t(lpszNamespaceURI)
    );
   return SUCCEEDED(hr);
  }
  catch( _com_error e)
  {
   TRACE( _T("CXsl::AddParameter( %s, %s, %s) failed:%s\n")
    , lpszParamName
    , lpszParamValue
    , lpszNamespaceURI
    , e.ErrorMessage()
    );
   ASSERT( FALSE );
   return FALSE;
  }
 }

 //-------------------------------------------------------------------------
 // Function Name    :TransformToFile
 // Parameter(s)     :CXml & objXml   the CXml instance
 //     :LPCTSTR lpszFilePath The destination file
 // Return           :BOOL
 // Create   :2008-1-16 16:38 Jerry.Wang
 // Memo             :Transform XML + XSL To File
 //-------------------------------------------------------------------------
 BOOL CXsl::TransformToFile( CXml & objXml, LPCTSTR lpszFilePath)
 {
  HRESULT hr     = S_FALSE;
  IStream * pOutStream  = NULL;
  LPVOID pOutput    = NULL;
  VARIANT_BOOL vbSuccessful = VARIANT_TRUE;

  try
  {
   ::CreateStreamOnHGlobal( NULL, TRUE, &pOutStream);
   m_pIXSLProcessor->put_output(_variant_t(pOutStream));

   hr = m_pIXSLProcessor->put_input( _variant_t((IUnknown*)objXml.m_pDoc) );
   if( FAILED(hr) ) { ASSERT(FALSE); return FALSE; }

   vbSuccessful = m_pIXSLProcessor->transform();
   if( vbSuccessful == VARIANT_FALSE ) { VERIFY(FALSE); return FALSE; }

   CXml::SaveStreamToFile( pOutStream, lpszFilePath);

   return TRUE;
  }
  catch( _com_error e)
  {
   TRACE( _T("CXsl::Transform failed:%s\n"), e.ErrorMessage());
   ASSERT( FALSE );
   return FALSE;
  }
 }
}

 

/////////////////////////////////////////////////////////////////////////////////使用XML//////////////////////////////////////////////////////////////////////////////////

CXml xml;
  BOOL bLoad;
  bLoad = xml.Open(fullPath);

  CXmlNodes xmlFaqnodes=xml.SelectNodes(_T("//FAQ/item"));
  int nCount=xmlFaqnodes.GetCount();
  TCHAR* szNo=NULL;
  TCHAR* szPesan=NULL;
  
  if (nCount)
  {
   m_dlgFaq.numbers++;
   for(int id=0;id    { 
    strFaqXml.Empty();
    m_dlgFaq.fnFaqRichFontBold();
   
    nQuestionNo++;
    strFaqXml = strFaqXml + nQuestionNo;
    strFaqXml +=_T(".");
    strFaqXml += xmlFaqnodes[id]->GetAttribute(_T("question"));
    //m_dlgFaq.m_richedit.ReplaceSel(strFaqXml);
   
//************************************************************************
    m_dlgFaq.m_strQues[id] = strFaqXml;
    switch (id)
    {
    case 0:
     m_dlgFaq.m_FaqQuesOne.SetWindowText(strFaqXml);
     break;
    case 1:
     m_dlgFaq.m_FaqQuesTwo.SetWindowText(strFaqXml);
     break;
    case 2:
     m_dlgFaq.m_FaqQuesThree.SetWindowText(strFaqXml);
     break;
    case 3:
     m_dlgFaq.m_FaqQuesFour.SetWindowText(strFaqXml);
     break;
    case 4:
     m_dlgFaq.m_FaqQuesFive.SetWindowText(strFaqXml);
     
     break;
    case 5:
     m_dlgFaq.m_FaqQuesSix.SetWindowText(strFaqXml);
     break;
    }
//************************************************************************
    m_dlgFaq.fnFaqRichFont();
    strFaqXml.Empty();
//    strFaqXml +=_T("\r\n");    
    strFaqXml += xmlFaqnodes[id]->GetAttribute(_T("answer1"));
    strFaqXml +=_T("\r\n");
    strFaqXml += xmlFaqnodes[id]->GetAttribute(_T("answer2"));
    strFaqXml +=_T("\r\n");
    strFaqXml += xmlFaqnodes[id]->GetAttribute(_T("answer3"));
    strFaqXml +=_T("\r\n\r\n");
    m_dlgFaq.m_richedit.ReplaceSel(strFaqXml);
    //************************************************************************
    m_dlgFaq.m_strAnsw[id] = strFaqXml;
    switch (id)
    {
    case 0:
     m_dlgFaq.m_FaqAnswerOne.SetWindowText(strFaqXml);
     break;
    case 1:
     m_dlgFaq.m_FaqAnswerTwo.SetWindowText(strFaqXml);
     break;
    case 2:
     m_dlgFaq.m_FaqAnswerThree.SetWindowText(strFaqXml);
     break;
    case 3:
     m_dlgFaq.m_FaqAnswerFour.SetWindowText(strFaqXml);
     break;
    case 4:
     m_dlgFaq.m_FaqAnswerFive.SetWindowText(strFaqXml);
     break;
    case 5:
     m_dlgFaq.m_FaqAnswerSix.SetWindowText(strFaqXml);
     break;
    }

 

你可能感兴趣的:(VC++)