封装Xml

本文介绍了一个用于操作XML文件的C++类CXmlFile,该类实现了IXmlFile接口,提供了包括打开、创建节点、删除节点、获取子节点等在内的多种XML文件操作功能。

#include <windows.h>

#include <streams.h>//测试过程中发现atlbase.h放在streams.h前面会导致debug版本内存错乱
#include <atlbase.h>

#include "ParseXml.h"
#import "msxml.dll" raw_interfaces_only

///////

#pragma once
class CXmlFile :public CUnknown,
 public IXmlFile
{
public:
 CXmlFile(LPCTSTR pName,  LPUNKNOWN pUnk);
public:
 virtual ~CXmlFile(void);

 DECLARE_IUNKNOWN

 static CUnknown * WINAPI CreateInstance (LPUNKNOWN punk, HRESULT *phr);
 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);

 STDMETHOD (Open)( BSTR strfile);
 STDMETHOD (CreateNode)( BSTR strName, IUnknown**ppNode);
 STDMETHOD (CreateTextNode)( BSTR strName, IUnknown**ppNode);
 STDMETHOD (DeleteNode)( IUnknown*pNode,BSTR strChildName);
 STDMETHOD (AppendChild)( IUnknown*pParentNode, IUnknown*pChildNode);
 STDMETHOD (GetChildCount)( IUnknown*pParentNode, LONG*pCount);
 STDMETHOD (GetChildNode)( IUnknown*pParentNode, BSTR strName, IUnknown**ppNode);
 STDMETHOD (GetChildNode2)( IUnknown*pParentNode, LONG index, IUnknown**ppNode);
 STDMETHOD (GetAttributeCount)( IUnknown*pNode, LONG* pCount);
 STDMETHOD (GetAttribute)( IUnknown*pNode, BSTR strAttributeName, VARIANT* value, VARIANT defValue);
 STDMETHOD (GetAttribute2)( IUnknown*pNode, LONG index, VARIANT* value, VARIANT defValue);
 STDMETHOD (SetAttribute)( IUnknown*pNode, BSTR strAttributeName, VARIANT value);
 STDMETHOD (GetText)( IUnknown*pNode, VARIANT* value, VARIANT defValue);
 STDMETHOD (SetText)( IUnknown*pNode, VARIANT value);
 STDMETHOD (GetValue)( IUnknown*pNode, BSTR strChildName, BSTR strAttributeName, VARIANT* value, VARIANT defValue);
 STDMETHOD (SetValue)( IUnknown*pNode, BSTR strChildName, BSTR strAttributeName, VARIANT value);
 STDMETHOD (Save)();
private:
 HRESULT QueryNode(IUnknown*pUnk,IXMLDOMNode**ppNode);
 HRESULT QueryElement(IUnknown*pUnk,IXMLDOMElement**ppElement);
private:
 BSTR              m_strFile;
 CComPtr<IXMLDOMDocument> m_pXmlDoc;
 CComPtr<IXMLDOMElement>    m_pRoot;
};

 

//////

#include "StdAfx.h"
#include "XmlFile.h"

CXmlFile::CXmlFile(LPCTSTR pName,  LPUNKNOWN pUnk)
:CUnknown(pName,pUnk),
m_strFile(NULL)
{
}

CXmlFile::~CXmlFile(void)
{
 if (m_strFile)
 {
  ::SysFreeString(m_strFile);
  m_strFile = NULL;
 }
}


CUnknown * CXmlFile::CreateInstance (LPUNKNOWN punk, HRESULT *phr)
{

 CUnknown*pObj = new CXmlFile(L"XmlFile",punk);
 if (pObj==NULL)
 {
  *phr = E_OUTOFMEMORY;
 }
 else
  *phr = S_OK;
 return pObj;
}

STDMETHODIMP CXmlFile::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
 if (riid == __uuidof(IXmlFile)) {
  GetInterface((IXmlFile*) this, ppv);
  return NOERROR;
 }
 else {
  return CUnknown::NonDelegatingQueryInterface(riid,ppv);
 }
}

HRESULT CXmlFile::Open( BSTR strfile)
{
 if (m_pRoot)  m_pRoot = NULL;
 if (m_pXmlDoc) m_pXmlDoc = NULL;
 if (m_strFile)
 {
  ::SysFreeString(m_strFile);
  m_strFile = NULL;
 }
 m_strFile = T2BSTR(strfile);

 HRESULT hr = E_FAIL;
 hr = m_pXmlDoc.CoCreateInstance(CLSID_DOMDocument);
 if (FAILED(hr)) return hr;

 if(PathFileExists(m_strFile))
 {
  VARIANT_BOOL bSuceess;
  hr = m_pXmlDoc->load(_variant_t(m_strFile),&bSuceess);
  if (FAILED(hr)|| !bSuceess) return hr;
  hr = m_pXmlDoc->get_documentElement(&m_pRoot);
 }
 else
 {
  hr = m_pXmlDoc->createElement(L"Xml",&m_pRoot);
  if (FAILED(hr)) return hr;
  hr = m_pXmlDoc->appendChild(m_pRoot,NULL);

 }
 if (FAILED(hr)) return hr;
}

HRESULT CXmlFile::CreateNode( BSTR strName, IUnknown**ppNode)
{
 return m_pXmlDoc->createElement(strName,(IXMLDOMElement **)ppNode);
}

HRESULT CXmlFile::CreateTextNode( BSTR strName, IUnknown**ppNode)
{
 return m_pXmlDoc->createNode(_variant_t(NODE_TEXT),strName,L"",(struct IXMLDOMNode * *)ppNode);
}

HRESULT CXmlFile::DeleteNode( IUnknown*pNode,BSTR strChildName)
{
 CComPtr<IXMLDOMNode> pParentNode;
 HRESULT hr = QueryNode(pNode,&pParentNode);
 if (FAILED(hr)||!pParentNode) return E_FAIL;
 
 CComPtr<IXMLDOMNode> pChildNode;
 hr = GetChildNode(pParentNode,strChildName,(IUnknown**)&pChildNode);
 if (SUCCEEDED(hr)&&pChildNode)
 {
  hr =  pParentNode->removeChild(pChildNode,NULL);
 }
 return hr; 
}

HRESULT CXmlFile::AppendChild( IUnknown*pParentNode, IUnknown*pChildNode)
{
 HRESULT hr = E_FAIL;
 if(!pChildNode) return hr;

 CComPtr<IXMLDOMNode> pNode;
 if(!pParentNode)
 {
  hr = m_pRoot.QueryInterface(&pNode);
  if(FAILED(hr)||!pNode) return hr;
 }
 else
 {
  hr = pParentNode->QueryInterface(__uuidof(IXMLDOMNode),(void**)&pNode);
  if(FAILED(hr)||!pNode) return hr;
  CComPtr<IXMLDOMNode> pParent;
  hr = pNode->get_parentNode(&pParent);//如果pParentNode节点还没有添加到xml中则返回错误
  if(FAILED(hr)||!pParent) return E_FAIL;
 }
 CComQIPtr<IXMLDOMNode,&__uuidof(IXMLDOMNode)> pNewNode(pChildNode);
 BSTR name = NULL;
 pNewNode->get_nodeName(&name);
 CComPtr<IUnknown> pUnk;
 hr = GetChildNode(pNode,name,&pUnk);
 if (name)
 {
  ::SysFreeString(name);
  name = NULL;
 }
 if (SUCCEEDED(hr)||pUnk)//节点存在就不让添加
 {
  return E_FAIL;
 }
 return pNode->appendChild(pNewNode,NULL);

}

HRESULT CXmlFile::GetChildCount( IUnknown*pParentNode, LONG*pCount)
{
 HRESULT hr = E_FAIL;
 if(!pCount) return hr;
 *pCount = 0;

 CComPtr<IXMLDOMNode> pNode;
 hr = QueryNode(pParentNode,&pNode);
 if(FAILED(hr)||!pNode) return hr;

 CComPtr<IXMLDOMNodeList> pNodeList;
 hr = pNode->get_childNodes(&pNodeList);
 if(FAILED(hr)||!pNodeList) return E_FAIL;
 return pNodeList->get_length(pCount);
}

HRESULT CXmlFile::GetChildNode( IUnknown*pParentNode, BSTR strName, IUnknown**ppNode)
{
 *ppNode = NULL;
 HRESULT hr = E_FAIL;
 CComPtr<IXMLDOMElement> pNode;
 hr = QueryElement(pParentNode,&pNode);
 if(FAILED(hr)||!pNode) return hr;

 CComPtr<IXMLDOMNodeList> pNodeList;
 hr = pNode->getElementsByTagName(strName,&pNodeList);
 if(FAILED(hr)||!pNodeList) return E_FAIL;
 long nCount;
 hr = pNodeList->get_length(&nCount);
 if(FAILED(hr)||nCount!=1) return E_FAIL;//保证childnode不同名
 return pNodeList->get_item(0,(IXMLDOMNode**)ppNode);
}

HRESULT CXmlFile::GetChildNode2( IUnknown*pParentNode, LONG index, IUnknown**ppNode)
{
 *ppNode = NULL;
 HRESULT hr = E_FAIL;
 CComPtr<IXMLDOMElement> pNode;
 hr = QueryElement(pParentNode,&pNode);
 if(FAILED(hr)||!pNode) return hr;

 CComPtr<IXMLDOMNodeList> pNodeList;
 hr = pNode->get_childNodes(&pNodeList);
 if(FAILED(hr)||!pNodeList) return E_FAIL;
 return pNodeList->get_item(index,(IXMLDOMNode**)ppNode);
}

HRESULT CXmlFile::GetAttributeCount( IUnknown*pNode, LONG* pCount)
{
 HRESULT hr = E_FAIL;
 if(pCount)
  *pCount = 0;
 else
  return hr;

 CComPtr<IXMLDOMNode> parrNode;
 hr = QueryNode(pNode,&parrNode);
 if(FAILED(hr)||!parrNode) return hr;

 CComPtr<IXMLDOMNamedNodeMap> pAttributeMap;
 hr = parrNode->get_attributes(&pAttributeMap);
 if (SUCCEEDED(hr)&&pAttributeMap)
 {
  hr = pAttributeMap->get_length(pCount);
 }
 return hr;
}

HRESULT CXmlFile::QueryNode(IUnknown*pUnk,IXMLDOMNode**ppNode)
{
 HRESULT hr = E_FAIL;
 if(!pUnk)
 {
  hr = m_pRoot.QueryInterface(ppNode);
 }
 else
 {
  hr = pUnk->QueryInterface(__uuidof(*ppNode),(void**)ppNode);
 }
 return hr;
}
HRESULT CXmlFile::QueryElement(IUnknown*pUnk,IXMLDOMElement**ppElement)
{
 HRESULT hr = E_FAIL;
 if(!pUnk)
 {
  hr = m_pRoot.QueryInterface(ppElement);
 }
 else
 {
  hr = pUnk->QueryInterface(__uuidof(*ppElement),(void**)ppElement);
 }
 return hr;
}
HRESULT CXmlFile::GetAttribute( IUnknown*pNode, BSTR strAttributeName, VARIANT* value, VARIANT defValue)
{
 HRESULT hr = E_FAIL;
 *value = defValue;

 CComPtr<IXMLDOMNode> parrNode;
 hr = QueryNode(pNode,&parrNode);
 if(FAILED(hr)||!parrNode) return hr;

 CComPtr<IXMLDOMNamedNodeMap> pAttributeMap;
 hr = parrNode->get_attributes(&pAttributeMap);
 if (SUCCEEDED(hr)&&pAttributeMap)
 {
  CComPtr<IXMLDOMNode> pAttribute;
  hr = pAttributeMap->getNamedItem(strAttributeName,&pAttribute);
  if (SUCCEEDED(hr)&&pAttribute)//属性存在,则修改改值
  {
   hr = pAttribute->get_nodeValue(value);
  }
 }
 return hr;
}

HRESULT CXmlFile::GetAttribute2( IUnknown*pNode, LONG index, VARIANT* value, VARIANT defValue)
{
 HRESULT hr = E_FAIL;
 *value = defValue;

 CComPtr<IXMLDOMNode> parrNode;
 hr = QueryNode(pNode,&parrNode);
 if(FAILED(hr)||!parrNode) return hr;

 CComPtr<IXMLDOMNamedNodeMap> pAttributeMap;
 hr = parrNode->get_attributes(&pAttributeMap);
 if(SUCCEEDED(hr)&&pAttributeMap)
 {
  CComPtr<IXMLDOMNode> pAttribute;
  hr = pAttributeMap->get_item(index,&pAttribute);
  if (pAttribute)
  {
   hr = pAttribute->get_nodeValue(value);
  }
 }
 return hr;
}

HRESULT CXmlFile::SetAttribute( IUnknown*pNode, BSTR strAttributeName, VARIANT value)
{
 HRESULT hr = E_FAIL;

 CComPtr<IXMLDOMNode> parrNode;
 hr = QueryNode(pNode,&parrNode);
 if(FAILED(hr)||!parrNode) return hr;

 CComPtr<IXMLDOMNamedNodeMap> pAttributeMap;
 hr = parrNode->get_attributes(&pAttributeMap);
 if (SUCCEEDED(hr)&&pAttributeMap)
 {
  CComPtr<IXMLDOMNode> pAttribute;
  hr = pAttributeMap->getNamedItem(strAttributeName,&pAttribute);
  if (SUCCEEDED(hr)&&pAttribute)//属性存在,则修改改值
  {
   hr = pAttribute->put_nodeValue(value);
  }
  else//属性不存在,则创建属性,并设置属性值
  {
   hr = m_pXmlDoc->createNode(_variant_t(NODE_ATTRIBUTE),strAttributeName,L"",&pAttribute);
   if (SUCCEEDED(hr)&&pAttribute)
   {
    hr = pAttribute->put_nodeValue(value);
    if (FAILED(hr)) return hr;
    hr = pAttributeMap->setNamedItem(pAttribute,NULL);
   }

  }
 }
 return hr;
}

HRESULT CXmlFile::GetText( IUnknown*pNode, VARIANT* value, VARIANT defValue)
{
 HRESULT hr = E_FAIL;
 *value = defValue;

 CComPtr<IXMLDOMNode> parrNode;
 hr = QueryNode(pNode,&parrNode);
 if(FAILED(hr)||!parrNode) return hr;

 return parrNode->get_nodeValue(value);
}

HRESULT CXmlFile::SetText( IUnknown*pNode, VARIANT value)
{
 HRESULT hr = E_FAIL;

 CComPtr<IXMLDOMNode> parrNode;
 hr = QueryNode(pNode,&parrNode);
 if(FAILED(hr)||!parrNode) return hr;

 return parrNode->put_nodeValue(value);
}

HRESULT CXmlFile::GetValue( IUnknown*pNode, BSTR strChildName, BSTR strAttributeName, VARIANT* value, VARIANT defValue)
{
 HRESULT hr = E_FAIL;

 CComPtr<IXMLDOMNode> pChildNode;
 hr = GetChildNode(pNode,strChildName,(IUnknown**)&pChildNode);
 if(FAILED(hr)||!pChildNode) return hr;

 return GetAttribute((IUnknown*)pChildNode,strAttributeName,value,defValue);

}

HRESULT CXmlFile::SetValue( IUnknown*pNode, BSTR strChildName, BSTR strAttributeName, VARIANT value)
{
 HRESULT hr = E_FAIL;

 CComPtr<IXMLDOMNode> pChildNode;
 hr = GetChildNode(pNode,strChildName,(IUnknown**)&pChildNode);
 if(FAILED(hr)||!pChildNode) return hr;

 return SetAttribute((IUnknown*)pChildNode,strAttributeName,value);
}

HRESULT CXmlFile::Save()
{
 if (m_pXmlDoc&&m_strFile)
 {
  return m_pXmlDoc->save(_variant_t(m_strFile));
 }
 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值