Skip to content

Instantly share code, notes, and snippets.

@lxfly2000
Last active August 3, 2019 05:21
Show Gist options
  • Save lxfly2000/26da59a477284c559b9f770ba390c6c0 to your computer and use it in GitHub Desktop.
Save lxfly2000/26da59a477284c559b9f770ba390c6c0 to your computer and use it in GitHub Desktop.
XML read/write using XMLLite.
#include<iostream>
#include<string>
#include<xmllite.h>
#include<atlmem.h>
#include<Shlwapi.h>
#pragma comment(lib,"xmllite.lib")
#pragma comment(lib,"shlwapi.lib")
struct HResultBase
{
HResultBase() :result(S_OK) {}
HResultBase(const HRESULT &_hr) :result(_hr) { Check(); }
virtual HRESULT operator=(const HRESULT &_hr)
{
result = _hr;
Check();
return Get();
}
bool operator==(const HRESULT &_hr) { return result == _hr; }
bool operator!=(const HRESULT &_hr) { return !operator==(_hr); }
virtual HRESULT Get()
{
return result;
}
protected:
virtual void Check()
{
if (FAILED(result))
std::cerr << "发生错误:" << result << std::endl;
}
HRESULT result;
};
struct HResultWriter:public HResultBase
{
HResultWriter(const HRESULT &_hr) :HResultBase(_hr) {}
HRESULT operator=(const HRESULT &_hr)
{
return HResultBase::operator=(_hr);
}
};
struct HResultReader :public HResultBase
{
HResultReader(const HRESULT &_hr) :HResultBase(_hr) {}
HRESULT operator=(const HRESULT &_hr)
{
result = _hr;
if (result == S_FALSE)
std::clog << "不存在属性。" << std::endl;
else Check();
return result;
}
};
//读取节点的属性
HRESULT DisplayAttributes(IXmlReader* pReader)
{
const WCHAR* pwszPrefix, *pwszLocalName, *pwszValue;
HResultReader hr = pReader->MoveToFirstAttribute();//跳到第一个属性,函数返回S_FALSE没有属性,其他的就应该是失败了
if (hr == S_FALSE)return hr.Get();//没有直接跳出
if (hr != S_OK)//失败,打印失败信息,不过我都一般会加上失败的位置
return hr.Get();
else
{
do
{
if (!pReader->IsDefault())
{
UINT cwchPrefix;
hr = pReader->GetPrefix(&pwszPrefix, &cwchPrefix);//获得节点命名空间的前缀
hr = pReader->GetLocalName(&pwszLocalName, NULL);//获取属性名称
hr = pReader->GetValue(&pwszValue, NULL);//获取属性值
if (cwchPrefix > 0)//分两种情况输出 有前缀和没有前缀
wprintf(L"Attr: %s:%s=\"%s\" \n", pwszPrefix, pwszLocalName, pwszValue);
else
wprintf(L"Attr: %s=\"%s\" \n", pwszLocalName, pwszValue);
}
} while (S_OK == pReader->MoveToNextAttribute());//移动到下一个属性
}
return hr.Get();
}
int main()
{
std::string strSection, strKey, strValue;
const TCHAR strFile[] = TEXT("settings.xml"), strUpdateFile[] = TEXT("update.xml");
CComPtr<IStream> pFileStream;
CComPtr<IXmlReader> pReader;
CComPtr<IXmlWriter> pWriter;
HResultWriter hrw = S_OK;
HResultReader hrr = S_OK;
std::cerr.setf(std::ios::right | std::ios::hex);
hrw = CreateXmlWriter(__uuidof(IXmlWriter), (void**)&pWriter, nullptr);//创建xmlWriter
hrr = CreateXmlReader(__uuidof(IXmlReader), (void**)&pReader, nullptr);
hrw = pWriter->SetProperty(XmlWriterProperty_Indent, TRUE);//设置xmlWriter属性
hrw = SHCreateStreamOnFile(strUpdateFile, STGM_CREATE | STGM_READWRITE, &pFileStream);
hrw = pWriter->SetOutput(pFileStream);
hrw = pWriter->WriteStartDocument(XmlStandalone_Omit);//写xml文件头
hrw = pWriter->WriteStartElement(NULL, TEXT("Update"), NULL);
hrw = pWriter->WriteElementString(NULL, TEXT("Version"), NULL, TEXT("1.0.0.1"));
hrw = pWriter->WriteElementString(NULL, TEXT("PatchURL"), NULL, TEXT("https://github.com/lxfly2000"));
hrw = pWriter->WriteElementString(NULL, TEXT("DownloadURL"), NULL, TEXT("http://blog.sina.com/lxfly2000"));
hrw = pWriter->WriteElementString(NULL, TEXT("ReleasePage"), NULL, TEXT("http://blog.sina.com/lxfly2000"));
hrw = pWriter->WriteEndElement();
hrw = pWriter->WriteEndDocument();
hrw = pWriter->Flush();
pFileStream.Release();
hrw = SHCreateStreamOnFile(strFile, STGM_CREATE | STGM_READWRITE, &pFileStream);//创建输出流
hrw = pWriter->SetOutput(pFileStream);//绑定输出流
hrw = pWriter->WriteStartDocument(XmlStandalone_Omit);//写xml文件头
//hrw = pWriter->WriteDocType(L"XML", NULL, NULL, NULL);//如果写上这句会在读的时候出一些问题
hrw = pWriter->WriteStartElement(NULL, TEXT("KaikiSettings"), NULL);
hrw = pWriter->WriteStartElement(NULL, TEXT("Joy"), NULL);
hrw = pWriter->WriteElementString(NULL, TEXT("Up"), NULL, TEXT("12"));
hrw = pWriter->WriteEndElement();
hrw = pWriter->WriteStartElement(NULL, TEXT("Program"), NULL);
hrw = pWriter->WriteElementString(NULL, TEXT("IsFullScreen"), NULL, TEXT("True"));
hrw = pWriter->WriteElementString(NULL, TEXT("IsDeveloper"), NULL, TEXT("False"));
hrw = pWriter->WriteEndElement();
hrw = pWriter->WriteEndElement();
hrw = pWriter->WriteEndDocument();
hrw = pWriter->Flush();
hrr = pFileStream->Seek({ 0i64 }, STREAM_SEEK_SET, NULL);
XmlNodeType nodeType;
const WCHAR* pwszPrefix, *pwszLocalName, *pwszValue;
UINT cwchPrefix;
//Open read-only input stream
//hrr = SHCreateStreamOnFile(strFile, STGM_READ, &pFileStream);//创建输入流
//hrr = CreateXmlReader(__uuidof(IXmlReader), (void**)&pReader, NULL);//创建XmlReader
hrr = pReader->SetProperty(XmlReaderProperty_DtdProcessing, DtdProcessing_Prohibit);//设置XmlReader的属性
hrr = pReader->SetInput(pFileStream);//将输入流绑定到XmlReader
//read until there are no more nodes
while (S_OK == (hrr = pReader->Read(&nodeType)))//循环 每次往前走一步
{
switch (nodeType)
{
case XmlNodeType_XmlDeclaration://如果是声明
wprintf(L"XmlDeclaration\n");
hrr = DisplayAttributes(pReader);
break;
case XmlNodeType_Element://如果是开始节点
hrr = pReader->GetPrefix(&pwszPrefix, &cwchPrefix);//获取节点前缀
hrr = pReader->GetLocalName(&pwszLocalName, NULL);//获取节点名称
if (cwchPrefix > 0)//分 有前缀和没有前缀两种情况输出
wprintf(L"Element: %s:%s\n", pwszPrefix, pwszLocalName);
else
wprintf(L"Element: %s\n", pwszLocalName);
hrr = DisplayAttributes(pReader);//输出节点属性
//hrr = pReader->MoveToElement();//要从属性 跳回到 节点
if (pReader->IsEmptyElement())//空的节点
wprintf(L" (empty)");
break;
case XmlNodeType_EndElement://关闭节点
hrr = pReader->GetPrefix(&pwszPrefix, &cwchPrefix);
hrr = pReader->GetLocalName(&pwszLocalName, NULL);//关闭节点的名称
if (cwchPrefix > 0)
wprintf(L"End Element: %s:%s\n", pwszPrefix, pwszLocalName);
else
wprintf(L"End Element: %s\n", pwszLocalName);
break;
case XmlNodeType_Text://值
hrr = pReader->GetValue(&pwszValue, NULL);//获取值
wprintf(L"Text: %s\n", pwszValue);
case XmlNodeType_Whitespace://这个其实是回车,我自己发现的
break;
case XmlNodeType_CDATA://这几个类型我没有用到
hrr = pReader->GetValue(&pwszValue, NULL);
wprintf(L"CDATA: %s\n", pwszValue);
break;
case XmlNodeType_ProcessingInstruction:
hrr = pReader->GetLocalName(&pwszLocalName, NULL);
hrr = pReader->GetValue(&pwszValue, NULL);
wprintf(L"Processing Instruction name:%s value:%s\n", pwszLocalName, pwszValue);
break;
case XmlNodeType_Comment:
hrr = pReader->GetValue(&pwszValue, NULL);
wprintf(L"Comment: %s\n", pwszValue);
break;
case XmlNodeType_DocumentType:
wprintf(L"DOCTYPE is not printed\n");
break;
}
}
pReader.Release();
pWriter.Release();
pFileStream.Release();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment