Last active
August 3, 2019 05:21
-
-
Save lxfly2000/26da59a477284c559b9f770ba390c6c0 to your computer and use it in GitHub Desktop.
XML read/write using XMLLite.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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