简介xmlstarlet是面向命令行环境的XML处理工具集此压缩包为1.6.1版本的Windows 32位可执行程序适合需要批量解析、校验、编辑XML的开发与运维人员。包内共15个文件约1.48MB除主程序xmlstarlet.exe外还包含PDF、HTML格式的使用手册以及txt说明、readme、ChangeLog、版权声明、News等文档涵盖txt、pdf、html、ps、css等多种格式方便查阅与打印。目前已有279人浏览学习。借助XPath支持可完成节点查询、XSD及Relax NG校验、节点增删改、格式化输出以及向HTML、JSON等格式转换等常见需求并可在批处理或脚本中组合使用实现XML数据的自动化处理减少手工编辑的重复劳动。附带的PDF/HTML手册和示例对快速上手与排查报错很有帮助对经常处理XML数据或编写自动化脚本的读者来说这是一款轻量但功能完整的实用工具。1. 拿到 xmlstarlet-1.6.1-win32.zip 之前先想清楚它能不能解决你的 XML 解析问题说实话我第一次在 Windows 机器上做 XML 解析时第一反应是装 Python、装 lxml直到有人甩给我一个 xmlstarlet 的压缩包。xmlstarlet 是纯粹的命令行 XML 工具集1.6.1 是修过一批历史 bug 的版本win32 后缀对应 32 位 Windows 环境整个包解压后不到 1MB不写注册表不依赖重型运行时。你拿它查节点、改字段、转格式、验 schema全都在一条命令里完成。它解决的是那种「就一段 XML要取两个值又嫌写脚本麻烦」的中间态问题。适合运维、测试、做数据交换的从业者也适合在受限环境里只能靠命令行干活的人。2. sel、ed、fo、val、tr五个核心子命令的分工与选型理由XMLStarlet 的设计思路和 Git 很像一个可执行文件内部按子命令拆功能。你不需要一次性学会全部日常 80% 的操作落在 sel查询和 fo格式化上剩下三个命令按场景补位。先把每个子命令的边界讲清楚再给一个串联使用的例子这样你在实际干活时才知道该用哪一个而不是五个命令挨个试。2.1 selXPath 查询是理解 XMLStarlet 的钥匙sel 是 select 的缩写负责「按 XPath 把节点取出来」。它也是第一个值得花时间研究的命令因为它的参数写法比 grep 多一层模板概念刚上手容易懵。xmlstarlet sel -t -m //book -v title -o | -v price -n books.xml这里的 -t 表示进入模板模式-m //book 是匹配所有 book 节点并对每个节点执行一次模板-v title 取当前节点的 title 子节点文本-o | 输出一个普通字符串做分隔-n 输出换行。逻辑上就是「对每本书打印标题、竖线、价格然后换行」。参数越简单越容易误用关键点有三个-t 必须出现在 -m 之前-m 后面跟的是 XPath 而不是文件路径-v 取的是文本值想要属性要写 -v id 这种带 的 XPath还有一个 -c 是复制整个节点含子节点和属性-x 是取 XPath 表达式的结果而不是模板输出。这三个取值参数分工不同新手最容易把 -v 和 -c 混用导致想取整个节点内容却只拿到一行文本。sel 的另一个高频场景是统计xmlstarlet sel -t -v count(//item) file.xml一行就能数出节点个数比写 Python 快得多。配合 -m 和 -b 还能做简单的分组汇总但遇到复杂聚合还是别硬撑导出以后交给脚本处理更合适。2.2 ed不打开文件就改 XML适合脚本化修改ed 是 edit 的缩写做的事情是在内存里对 XML 做增删改然后把结果输出到标准输出。它有两个关键操作-u 更新已有节点文本-d 删除节点-a 在锚点节点之后插入-i 在锚点节点之前插入。xmlstarlet ed -u /config/timeout -v 300 app.xml这条命令把 /config/timeout 节点的文本改成 300。两点必须注意第一ed 默认不会覆盖原文件它把改完的 XML 打印出来你要么用重定向 保存到新文件要么用 -L 或 --inplace 直接写回原文件。第二如果 XPath 匹配到多个节点-u 会全部更新想只改第一个要写成 /config/timeout[1]。增删节点时-a 和 -i 需要配合 -t 指定节点类型例如xmlstarlet ed -a /config -t elem -n debug -v false app.xml表示在 config 末尾追加一个 debug 节点。这一串参数第一次看很绕但多练两次就顺了。我一般会把 ed 和 sel 连起来用先 sel 确认 XPath 能取到值再 ed 去改能避免「XPath 写错但命令还是成功执行」的静默问题。2.3 fo格式化与标准化接手别人 XML 的第一件事fo 是 format 的缩写同时具备缩进重排和序列化输出两个能力。拿到一个被压缩成一行、或者缩进混乱的 XML第一条命令永远是 fo。xmlstarlet fo -t -n messy.xml clean.xml-t 表示输出缩进-n 表示输出换行把「一行流」展开成可读的多行结构。还有一个重要参数 -R全称 --recover它让解析器进入容错模式遇到非法字符或标签不闭合时尽量恢复而不是直接报错。这个参数在解析爬虫抓下来的半残 XML 时非常有用但输出不保证语义正确只能作为抢救手段恢复正常后的 XML 还是要用 val 校验一遍。fo 还有一个容易被忽略的用途统一换行符和引号风格。它会把属性值的单引号统一成双引号把换行符按当前平台处理。这样一来两个来源不同的 XML 放到 diff 工具里对比时不会被换行符差异刷屏diff 结果干净很多。2.4 tr 与 valXSLT 转换和 schema 校验的兜底tr 是 transform 的缩写执行 XSLT 1.0 转换把 XML 按样式表变成 HTML、文本或另一种结构的 XML。它适合「同一个数据源要输出多种视图」的场景比如把配置文件转成文档。val 是 validate 的缩写支持 DTD、XSD、Relax NG 三种校验方式。xmlstarlet val -e -s schema.xsd app.xml-e 表示出错时打印详细错误信息-s 指定 schema 文件。如果 app.xml 不符合 schema命令会输出行号和元素路径。上线前用 val 跑一遍比在业务代码里被解析器报错再回头查要省心得多。这两个命令的定位是「兜底」日常改动 XML 之后顺手跑一次能挡住大部分低级错误。2.5 一次完整的改配置流程sel 确认、ed 修改、fo 整理、val 收尾把上面四个命令串成一个真实场景某个服务的配置文件 config.xml 里timeout 节点需要从 120 改成 300而且文件本身是压缩成一行的那种。xmlstarlet sel -t -v /config/timeout config.xml xmlstarlet ed -u /config/timeout -v 300 config.xml config.new.xml xmlstarlet fo -t -n config.new.xml config.pretty.xml xmlstarlet val -e -s config.xsd config.pretty.xml第一行确认当前值是 120第二行把值改成 300 并输出到新文件第三行把新文件格式化第四行用 schema 校验。每一步都能看到中间结果出错能定位到具体命令不用把整个流程当成黑匣子。实际工作中我会把第二行的结果先落到临时文件检查无误后再替换原文件等于给自己留了后悔药。3. win32 版本在 Windows 上的安装、环境变量与编码实战3.1 安装包解压、目录结构与 PATH 配置xmlstarlet-1.6.1-win32.zip 解压后目录里会有 xmlstarlet.exe 和若干运行时 DLL没有安装程序这一点和大多数 Windows 软件不一样。它的运行不依赖注册表拷贝到任意目录都能跑。我习惯放在 C:\tools\xmlstarlet-1.6.1 下然后把该目录加进系统 PATH这样在任意路径下直接敲 xmlstarlet 都能识别不用每次带全路径。配置 PATH 分三步WinR 打开运行输入 sysdm.cpl 回车切到「高级」选项卡点「环境变量」在「系统变量」里找到 Path编辑新建一行填入 C:\tools\xmlstarlet-1.6.1重新打开一个 cmd 窗口执行下面的命令验证。xmlstarlet --version输出里会带 XMLStarlet 1.6.1 和编译平台信息。如果提示「不是内部或外部命令」说明 PATH 没配好或者当前 cmd 是配置之前打开的重开窗口通常能解决。这里有个容易踩的细节32 位程序在 64 位 Windows 上运行没有问题但安装路径建议避开空格和中文因为 cmd 解析带空格的路径容易翻车写成 Program Files 目录时尤其明显。3.2 编码是第一道坎UTF-8 文件与 GBK 控制台的错位Windows 中文版 cmd 默认代码页是 GBK936而绝大多数 XML 文件声明的是 UTF-8。XMLStarlet 按 XML 声明的编码读取文件输出时却按控制台代码页写于是你经常看到「中文变成问号」或者输出乱码。解决有三个层次。第一层是改控制台代码页chcp 65001执行后当前窗口切到 UTF-8 代码页再次运行 xmlstarlet 输出就正常了。但 chcp 只对当前窗口生效关掉重开就失效。提示chcp 65001 只对当前窗口生效别把它写进系统级的启动脚本里否则某些老程序会跟着乱码。第二层是不依赖控制台显示直接把输出重定向到文件xmlstarlet sel -t -m //book -v title -n books.xml titles.txt此时 XMLStarlet 的输出直接写进文件不受控制台代码页影响。第三层是强制指定输入编码如果 XML 文件没有声明 encoding或者声明与真实编码不一致XMLStarlet 可能按错误方式解析这时用 --encoding 显式指定xmlstarlet fo --encoding UTF-8 messy.xml clean.xml--encoding 同时影响读取和输出。但如果文件本身是 GBK 编码且没有声明显式指定 UTF-8 会报错或产生乱码。遇到这种文件先用文本编辑器确认真实编码再决定参数不要猜。3.3 实战解析一份接口返回的 XML 响应模拟一个真实场景某服务返回的 resp.xml 里需要提取所有 order 节点的 id 和 amount并统计总金额。xmlstarlet sel -t -m //order -v concat(id, ,, amount) -n resp.xml xmlstarlet sel -t -v sum(//order/amount) resp.xml第一条命令输出每个订单的 id 和金额逗号分隔第二条直接用 XPath 的 sum 函数累加所有 amount 节点的文本值。这个场景里-m 循环遍历每个 order-v 内部可以用 XPath 函数 concat 做字符串拼接比用多个 -o 更紧凑。注意 amount 节点必须包含可解析的数值文本否则 sum 会静默返回 0这一点要靠看输出结果来确认命令本身不报错。3.4 配合其他 Windows 命令做管道处理XMLStarlet 和 findstr、more 等 Windows 原生命令配合也能干活但有一个坑管道传递时编码会经过 cmd 的代码页转换。xmlstarlet sel -t -m //error -v code -n resp.xml | findstr 500如果 resp.xml 是 UTF-8 而 findstr 期望 GBK 环境输出可能对不上。我的经验是在 Windows cmd 里能不过管道就不过正确的做法是先把 xmlstarlet 的结果重定向到临时文件再用 findstr 读文件。这比折腾管道编码省事得多尤其是处理中文环境下的日志时。4. 常见问题与避坑error 1935、路径转义与乱码排查这一节全是血泪经验大部分问题集中在三件事运行时组件缺失、Windows 路径转义、编码混乱。每条按「现象 → 原因 → 解决」的顺序写你可以直接对照自己的报错信息定位。4.1 安装或首次运行时遇到 error 1935现象在某些 Windows 机器上首次运行 xmlstarlet.exe 或安装相关组件时弹出错误提示提到 error 1935伴随「安装程序集 microsoft.vc8o.atl, typewin32, version8.0.5072...」这样的描述。原因1.6.1 是较早期版本依赖 Visual C 2005VC8运行库其中 ATL 程序集对应 C 的 Active Template Library 组件。这台机器恰好没有装相应的 VC8 运行库或者系统里残留的版本损坏导致 Windows Installer 无法完成程序集注册。能不能装上有时带点玄学同一台机器换个用户身份可能结果不同。解决安装 VC 2005 SP1 可再发行组件x86 版本装完重开命令行再试。如果安装过程本身报 error 1935用静默方式安装VC2005SP1_x86.exe /quiet /norestart静默安装完成后重新打开 cmd 执行 xmlstarlet --version 验证。注意64 位 Windows 自带的 VC 运行库通常是 x64解决不了 32 位程序的依赖。x86 版本必须单独装。如果还是报同样的错检查系统里是否残留旧版本运行库卸载后重新装一遍。4.2 Windows 路径里的反斜杠导致 XPath 取不到值现象运行xmlstarlet sel -t -v /config/setting[1]/name时命令没有报错但没有任何输出。把文件路径写成 D:\data\app.xml 传给命令偶尔也出问题。原因XPath 表达式里的路径分隔符必须用正斜杠 /与文件系统无关。另外 cmd 对反斜杠的转义规则很诡异参数里出现 \ 时可能被吞掉或转义导致整个表达式失效。解决XPath 内一律用正斜杠文件路径推荐用正斜杠或者用双引号包住完整路径。xmlstarlet sel -t -v /config/setting[1]/name D:/data/app.xml注意双引号在 cmd 里不是消灭转义问题的万能药。如果路径本身带空格还要多包一层如果路径里出现 %USERPROFILE% 这类环境变量XMLStarlet 不会自动展开稳妥做法是先用 set 赋值再用或者直接用绝对路径。4.3 带 BOM 的 UTF-8 文件解析报错或首个节点取不到现象解析同事导出的 XML命令报错指向文件开头或者 sel 取第一个节点时结果里出现一个不可见字符。原因文件开头有 UTF-8 BOM 头。XML 规范允许解析器识别 BOM但 1.6.1 的解析器在某些操作上对 BOM 处理不干净尤其容易把它当成文本内容的一部分送进模板输出。解决先格式化重写一次文件让 XMLStarlet 自己序列化一遍xmlstarlet fo -t -n input.xml input.clean.xml如果 fo 也报错用文本编辑器把文件另存为「UTF-8 无 BOM」再跑 fo。从那以后我只要拿到外部来的 XML 第一件事就是 fo 一遍既整理了缩进又清掉了 BOM一举两得。4.4 sel 查不到任何值但退出码仍然是 0现象跑完xmlstarlet sel ... -v //nonexistent file.xml没有任何输出但命令执行是成功的退出码 0。在脚本里用 errorlevel 判断是否成功结果误判。原因XMLStarlet 的 sel 设计如此XPath 匹配不到节点会被当作「合法空结果」不是错误。这在命令行交互时无所谓但放进批处理脚本里就会埋雷脚本会以为查询成功继续往下走。解决脚本里不要只用退出码判断要结合输出内容或者先跑一个 count 探测节点数量xmlstarlet sel -t -v count(//order) resp.xml把它放进 if 条件判断数量为 0 时走另一条分支。另一种做法是先跑 val -e 确认文档结构合法再跑 sel两件事分开错误定位就清楚了。4.5 大文件解析慢得离谱先确认是不是单线程瓶颈现象解析一个 200MB 的 XML命令执行时间长到像卡死进度半天不动。原因XMLStarlet 是单线程的而且内部是基于 DOM 构建的32 位进程的地址空间有限大文件既慢又容易触发内存不足。解决超过 100MB 的 XML 不建议用 1.6.1 硬扛改用流式处理工具或者先按顶层元素把文件切割成小块再逐个交给 XMLStarlet。如果只是取个别字段可以用 grep 先粗筛再精解析别让一个 DOM 把内存撑爆。命令行小工具再方便也有能力边界。5. 进阶技巧用 sel 的模板输出把 XML 批量转成 CSV最后分享一个我一直在用的技巧用 sel 的 -m、-o、-v 组合把嵌套的 XML 拍平成 CSV省掉中间写脚本的步骤。原理是模板模式本身就像一个小型循环对每个匹配节点执行一组固定的输出动作。xmlstarlet sel -t -m //book -v id -o , -v title -o , -v substring(price, 1, 5) -n books.xml books.csv这条命令把每本书的 id、书名、截断后的价格拼成一行 CSV-n 在每行末尾换行。XPath 函数可以直接写进 -v格式化都在表达式里完成不需要额外脚本。批量处理多个文件时用 for 循环包一层for %f in (*.xml) do xmlstarlet sel -t -m //book -v id -o , -v title -n %f all_books.csv在 cmd 里跑要写单百分号 %f在批处理文件里要写双百分号 %%f。这个区别我至少翻过两次车现在每次写循环前都会提醒自己检查当前是命令行还是脚本文件。输出重定向用 追加而不是 覆盖多个文件的结果才能合到同一个 CSV。字段内容如果本身包含逗号先看数据里是否出现分隔符必要时改用 -o | 做竖线分隔。最后打开文件确认行数与源节点数一致数量对不上就回头查 XPath 里的匹配条件。从那以后我每次拿到新的 XML 数据源都强制走一遍「fo 看结构、sel 拍平、val 验证」的流程三个命令各管一段基本没有返工过。xmlstarlet 这套工具链虽然老但在 Windows 32 位环境里依然是把好手如果你是同样环境又要经常碰 XML直接下载这份 xmlstarlet-1.6.1-win32.zip 就能用希望这份经验帮到你。本文还有配套的精品资源点击获取