#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));
}
}
本文介绍了一个用于操作XML文件的C++类CXmlFile,该类实现了IXmlFile接口,提供了包括打开、创建节点、删除节点、获取子节点等在内的多种XML文件操作功能。
234

被折叠的 条评论
为什么被折叠?



