示例工程【免费下载链接】Windows-classic-samplesThis repo contains samples that demonstrate the API used in Windows classic desktop applications.项目地址https://gitcode.com/gh_mirrors/wi/Windows-classic-samples点击查看免费下载本文以 Windows-classic-samples 仓库中的 XmlLiteReaderWriter 示例 为主线讲解如何基于 Windows 内置的 XmlLite 库完成读取 XML → 逐节点处理 → 写出新 XML的完整闭环并深入源码剖析其背后的事件流式模型、IStream适配原理与编码处理细节。读完本文你将掌握IXmlReader/IXmlWriter的配对用法能够独立实现在流式解析过程中改写节点内容的 XML 转换工具。示例概览一次打 25% 折扣的 XML 转换仓库中的示例程序XmlLiteReaderWriter.cpp演示了 XmlLite 最典型的应用场景读入一个描述图书价格的 XML 文档 books.xml在流式解析过程中把每个price元素的价格统一打 25% 折扣并为该元素追加originalPrice原始价格与discount折扣比例两个属性最后把变换后的 XML 完整写出到另一个文件。输入的 books.xml 内容如下books book nameMy First Book price100.00/price /book book nameA Less Expensive Book price25.00/price /book /books程序预期产出的结果在源码注释中给出了清晰的示意XmlLiteReaderWriter.cpp 的注释块books book nameMy First Book price originalPrice100.00 discount25% 75.000000 /price /book book nameA Less Expensive Book price originalPrice25.00 discount25% 18.750000 /price /book /books这个例子虽然简单却完整覆盖了 XmlLite 的核心能力读取read、逐节点遍历iterate、节点变换transform与写出write是理解 XmlLite 编程模型的最佳起点。XmlLite 是什么高性能、易用、符合 XML 1.0 标准根据示例 README 的介绍XmlLite 是一套面向 Windows 的 XML 处理库它让开发者能够构建高性能的 XML 应用并与其他遵循 XML 1.0 标准的应用保持高度互操作。XmlLite 的设计目标可以概括为三点易用性ease of use以 COM 接口IXmlReader、IXmlWriter暴露能力接口数量少、职责清晰性能performance采用拉模式pull-based流式解析不把整棵文档树加载进内存内存占用与文档大小无关标准符合性standards compliance遵循 XML 1.0 规范支持 DTD 处理策略配置等标准特性。XmlLite 以动态链接库形式随 Windows 提供任何能调用 DLL 的 Windows 语言都可以使用它但微软官方推荐使用 CREADME 原文为 Microsoft recommends C并且 XmlLite 自带全套 C 支持文件。本示例的源码正是用标准 C COM 风格编写的。注意README 中同时说明本仓库Windows-classic-samples为每个示例都提供了 Visual Studio 解决方案.sln、源文件、资源与元数据用于编译和运行本示例针对 Windows 8.1 / Windows Server 2012 R2 使用 Visual Studio 2013 创建但多数情况下在更高版本的工具链上可以不加修改直接运行。工程构成与构建方法示例的工程文件位于Samples/XmlLiteReaderWriter/cpp/目录下包含四个文件文件作用XmlLiteReaderWriter.cpp全部业务逻辑FileStream、读取、变换、写出books.xml示例输入 XML即待打折的图书价格清单xmllitereaderwriter.slnVisual Studio 解决方案文件xmllitereaderwriter.vcxproj工程定义配置、编译与链接选项从xmllitereaderwriter.vcxproj中可以确认关键的工程配置链接依赖Debug 与 Release 两个配置都在AdditionalDependencies中加入了xmllite.lib;%(AdditionalDependencies)见 vcxproj 第 52 行与第 66 行。xmllite.lib是 XmlLite 的导入库运行时对应xmllite.dllWindows 8 及后续系统均内置。字符集两个配置均设置为Unicode这与源码使用宽字符WCHAR、wprintf、L...的写法一致。平台工具集工程使用v110对应 Visual Studio 2012 工具集README 推荐使用 Visual Studio 2013 或更高版本打开遇到工具集版本差异时 Visual Studio 通常会提示自动升级。优化选项Release 配置启用了WholeProgramOptimization、FunctionLevelLinking、IntrinsicFunctions等体现了对高性能目标的追求。构建步骤用 Visual Studio 打开Samples/XmlLiteReaderWriter/cpp/xmllitereaderwriter.slnVisual Studio 2013 及以上版本均可按F7或 Visual Studio 2013 中的F6或通过菜单Build → Build Solution构建构建产物默认生成在Debug或Release输出目录下程序名为XmlLiteReaderWriter.exe。运行步骤程序需要两个命令行参数输入 XML 文件名和输出 XML 文件名例如XmlLiteReaderWriter.exe books.xml output.xml在 Visual Studio 中可以直接按F5带调试运行或CtrlF5不带调试运行执行若直接运行请确保books.xml与可执行文件位于同一目录或传入完整路径。核心机制一自实现 FileStream向 XmlLite 提供IStreamXmlLite 的读写器并不直接接收文件路径而是接收 COM 流对象IStream。因此源码开头定义了一个从IStream派生的FileStream类XmlLiteReaderWriter.cpp 第 37 行起把 Win32 文件句柄包装成 XmlLite 可消费的流HRESULT static OpenFile(LPCWSTR pName, IStream ** ppStream, bool fWrite) { HANDLE hFile ::CreateFileW(pName, fWrite ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, NULL, fWrite ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ... *ppStream new FileStream(hFile); return S_OK; }关键设计点读写方向复用OpenFile通过fWrite布尔参数决定CreateFileW的访问方式——读取时用GENERIC_READOPEN_EXISTING写入时用GENERIC_WRITECREATE_ALWAYS覆盖创建。同一套流类同时服务输入与输出两个方向。最小化 IStream 实现FileStream完整实现了QueryInterface/AddRef/Release引用计数用InterlockedIncrement/Decrement保证线程安全以及Read/Write内部转调ReadFile/WriteFile和Seek/Stat而SetSize、CopyTo、Clone、LockRegion等 XmlLite 用不到的方法则返回E_NOTIMPL。这说明向 XmlLite 喂流只需实现它真正会调用的那部分接口。错误映射底层 Win32 失败统一通过HRESULT_FROM_WIN32(GetLastError())转换为HRESULT与 XmlLite 的 COM 错误模型无缝衔接。核心机制二reader / writer 的创建、输入输出绑定与关键属性1. 创建读写器并绑定流主流程wmainXmlLiteReaderWriter.cpp 第 189 行起按标准套路完成初始化CreateXmlReader(__uuidof(IXmlReader), (void**) pReader, NULL); CreateXmlReaderInputWithEncodingCodePage(pFileStream, NULL, 65001, FALSE, Lc:\temp, pReaderInput); CreateXmlWriter(__uuidof(IXmlWriter),(void**) pWriter, NULL); CreateXmlWriterOutputWithEncodingCodePage(pOutFileStream, NULL, 65001, pWriterOutput); pReader-SetInput(pReaderInput); // 把输入流交给 reader pWriter-SetOutput(pWriterOutput); // 把输出流交给 writer这里展示了 XmlLite 的工厂函数 适配器对象架构CreateXmlReader/CreateXmlWriter创建读写器对象本体CreateXmlReaderInputWithEncodingCodePage/CreateXmlWriterOutputWithEncodingCodePage分别把IStream包装成IXmlReaderInput/IXmlWriterOutput并在此指定字符编码——两个调用都使用了代码页65001即UTF-8这是最常见的 Web 文本编码也解释了示例输入 books.xml 为何以 UTF-8 存储最后通过SetInput/SetOutput把适配器挂接到读写器上完成绑定。2. 安全与格式属性绑定完成后示例设置了两处重要属性pReader-SetProperty(XmlReaderProperty_DtdProcessing, DtdProcessing_Prohibit); pWriter-SetProperty(XmlWriterProperty_Indent, TRUE);XmlReaderProperty_DtdProcessingDtdProcessing_Prohibit禁止处理输入中的 DTD。这是推荐的安全做法可以规避 XML 实体展开billion laughs 等带来的潜在风险。XmlLite 还提供DtdProcessing_Parse与DtdProcessing_Skip两个取值可按需放宽。XmlWriterProperty_IndentTRUE让输出自动缩进、美化排版便于人工阅读生成的 XML。核心机制三事件流式遍历 节点级变换的算法示例的核心处理逻辑是wmain中的一个while循环XmlLiteReaderWriter.cpp 第 304 行起while (S_OK (hr pReader-Read(nodeType))) { switch (nodeType) { case XmlNodeType_Element: ... case XmlNodeType_Text: ... case XmlNodeType_EndElement: ... default: ... } }IXmlReader::Read每次推进一个节点并把节点类型写入nodeType直到文档结束返回S_FALSE。这种拉模式pull事件流与 SAX 的推送式回调相反解析进度由调用方控制天然适合边读边改写再写出的流水线。WriteNodeShallow 与 WriteNode 的关键区别源码注释特别强调了一个极易踩坑的点在while (Read(...))循环内部必须使用WriteNodeShallow而非WriteNode因为WriteNode会把 reader 推进到下一个节点若在循环里使用它每轮循环都会跳过一个节点。WriteNodeShallow只写出当前节点的浅层表示不含子节点不移动 reader。示例代码在 Element / Text / 默认分支中统一使用WriteNodeShallow(pReader, FALSE)第二个参数fWriteByteOrderMark传FALSE不额外写 BOM。折扣变换的三种节点分支对XmlNodeType_Element元素开始、XmlNodeType_Text文本、XmlNodeType_EndElement元素结束三种节点类型示例采用了不同的处理策略Element元素开始通过pReader-GetQualifiedName(pQName, NULL)取元素名注释提示不关心长度时第二个参数可传NULL以获得更快的执行判断是否为price。是则置inPrice TRUE否则置FALSE随后用WriteNodeShallow原样写出该元素的开始标签。IsEmptyElement()用于识别自闭合的空元素空元素直接浅层写出、不做变换。Text文本节点若当前处于inPrice状态则读取文本值pReader-GetValue(pValue, NULL)用_wtof转成浮点数后乘以0.75即打 25% 折扣再通过StringCbPrintfW格式化回字符串。随后依次调用pWriter-WriteAttributeString(NULL, LoriginalPrice, NULL, pValue)——写入原始价格属性pWriter-WriteAttributeString(NULL, Ldiscount, NULL, L25%)——写入折扣属性pWriter-WriteString(priceString)——写入折后价文本。EndElement元素结束再次读取元素名若是price则复位inPrice FALSE并调用pWriter-WriteFullEndElement()写出完整的结束标签而非自闭合形式。这样price元素的开始标签由WriteNodeShallow写出其内部文本被替换为折后价并插入两个新属性结束标签由WriteFullEndElement补齐——一次读改写的流式变换就此完成。示例输入 books.xml 中100.00与25.00两个价格经变换后分别成为75.000000与18.750000。值得注意的细节pWriter-WriteAttributeString在 writer 写出元素的开始标签之后、写入内容之前调用这是 XmlLite 对属性必须在元素内容之前写出这一 XML 约束的体现。统一错误处理与资源清理模式源码通过宏 集中式goto CleanUp实现了简洁而统一的错误与资源管理#define CHKHR(stmt) do { hr (stmt); if (FAILED(hr)) goto CleanUp; } while(0) #define HR(stmt) do { hr (stmt); goto CleanUp; } while(0) #define SAFE_RELEASE(I) do { if (I){ I-Release(); } I NULL; } while(0)每个 XmlLite 调用后都检查HRESULT失败即打印形如Error creating xml reader, error is %08.8lx的错误信息并跳转清理CleanUp标签处用SAFE_RELEASE逐一释放pFileStream、pOutFileStream、pReader、pWriter、pReaderInput、pWriterOutput六个 COM 对象最后返回hr作为进程退出码这一模式对 COM 风格编程具有普遍参考价值所有通过工厂函数获得的接口都必须配对 Release防止流对象与读写器造成资源泄漏。从本示例延伸XmlLite 的典型应用场景本示例展示的reader writer 流式流水线正是 XmlLite 在真实应用中最有代表性的用法可直接迁移到以下场景配置文件的读取与改写应用配置通常是结构化的 XML可在不重建整棵文档树的前提下流式替换某个配置节点的值XML 数据清洗与迁移批量修正历史 XML 数据如统一字段命名、格式化数值、追加元数据属性内存占用稳定适合处理大文件流式转换管道作为中间环节串联 XML 解析与序列化如把一种 XML 方言转换为另一种安全加固处理配合DtdProcessing_Prohibit等属性在解析不可信 XML 时规避实体注入类攻击。若需要遍历文档整体结构或做 XPath 查询XmlLite 并非唯一选择可配合 MSXML 的 DOM 模型使用仓库中另有 MSXML 系列示例但若追求低内存、高性能的流式处理XmlLite 的 reader/writer 组合是 Windows 平台上的首选方案。读者若想进一步研究 XmlLite 的其他用法可对比仓库中 XmlLiteReader 示例、XmlLiteWriter 示例 等姊妹示例它们分别聚焦读取与写入的单项能力与本示例构成完整的参考体系。小结要点内容示例功能读取 books.xml对price打 25% 折扣并追加originalPrice/discount属性后写出新文件核心 APICreateXmlReader、CreateXmlWriter、CreateXmlReaderInputWithEncodingCodePage、CreateXmlWriterOutputWithEncodingCodePage流适配自定义FileStream : IStream包装 Win32 文件句柄关键属性reader 禁用 DTD 处理writer 开启缩进UTF-8代码页 65001遍历模型IXmlReader::Read拉模式事件流 WriteNodeShallow/WriteFullEndElement/WriteAttributeString/WriteString组合写出链接依赖xmllite.lib对应系统内置xmllite.dll运行环境面向 Windows 8.1 / Windows Server 2012 R2Visual Studio 2013 及以上可编译运行XmlLiteReaderWriter 用约 400 行代码完整呈现了 XmlLite 读取—遍历—变换—写出 的端到端能力从自实现IStream到 reader/writer 的创建与绑定从流式节点遍历到节点级属性与文本改写再到统一错误处理与 COM 资源释放每一个环节都是可复用的最佳实践模板。对照仓库中该示例的 源码 与 输入数据你可以立即上手把它改造为自己的 XML 处理工具。赞分享示例工程【免费下载链接】Windows-classic-samplesThis repo contains samples that demonstrate the API used in Windows classic desktop applications.项目地址https://gitcode.com/gh_mirrors/wi/Windows-classic-samples点击查看免费下载相关推荐Windows-classic-samples 的 XmlLiteReader 示例用 XmlLite 流式解析 XML 文档的实战指南Windows classic samples 的 XmlLiteReader 示例用 XmlLite 流式解析 XML 文档的实战指南 本文以 Window示例工程Windows-classic-samples 之 XmlLiteNamespaceWriter1用 XmlLite 写出带命名空间前缀的 XML 文档Windows classic samples 之 XmlLiteNamespaceWriter1用 XmlLite 写出带命名空间前缀的 XML 文档 本文示例工程用 XmlLite 写出带编码声明的 XML 文档Windows-classic-samples XmlLiteWriteWithEncoding 示例深度解析用 XmlLite 写出带编码声明的 XML 文档Windows classic samples XmlLiteWriteWithEncoding 示例深度解示例工程上一篇网页版微信无法登录的终极解法wechat-need-web 跨浏览器解锁工具上手指南下一篇MTKClient实战指南联发科设备救砖、刷机与Bootloader解锁完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?