使用xmlstarlet向DocBook XML文件添加revision节点失败如何解决
问题原因
你的目标XML文件定义了默认命名空间xmlns="http://docbook.org/ns/docbook",你原命令中使用的无命名空间前缀的XPath路径/book/info/revhistory无法匹配到任何节点,因此命令执行后不会产生修改效果。同时xmlstarlet默认不会原地修改文件,如果你没有加对应参数,修改结果只会输出到终端,不会写入原文件。
解决方案1:修正xmlstarlet命令
通过-N参数绑定命名空间别名,同时添加-L参数开启原地修改即可,修正后的命令如下:
xmlstarlet edit -L \ -N d="http://docbook.org/ns/docbook" \ -s /d:book/d:info/d:revhistory --type elem --name revisionTMP --value "" \ -s /d:book/d:info/d:revhistory/revisionTMP --type elem --name revnumber --value "Online" \ -s /d:book/d:info/d:revhistory/revisionTMP --type elem --name date --value "Jul 2022" \ -s /d:book/d:info/d:revhistory/revisionTMP --type elem --name revremark --value "Version 2.5" \ -r /d:book/d:info/d:revhistory/revisionTMP -v revision \ ./test_book.xml
参数说明:
-N d="http://docbook.org/ns/docbook":将默认DocBook命名空间绑定到别名d,后续XPath路径中对应节点都需要加上d:前缀才能匹配-L:开启原地修改模式,修改结果直接写入原文件
解决方案2:Python lxml实现(更适合复杂场景)
如果需要处理更复杂的XML修改逻辑,可以用Python的lxml库实现,示例脚本如下:
from lxml import etree # 命名空间配置 NS = { "d": "http://docbook.org/ns/docbook", "xi": "http://www.w3.org/2001/XInclude" } # 读取XML文件 tree = etree.parse("test_book.xml") # 定位修订历史节点 revhistory = tree.xpath("/d:book/d:info/d:revhistory", namespaces=NS)[0] # 构建新修订节点 revision = etree.SubElement(revhistory, "{" + NS["d"] + "}revision") revnumber = etree.SubElement(revision, "{" + NS["d"] + "}revnumber") revnumber.text = "Online" date = etree.SubElement(revision, "{" + NS["d"] + "}date") date.text = "Jul 2022" revremark = etree.SubElement(revision, "{" + NS["d"] + "}revremark") revremark.text = "Version 2.5" # 写入修改后的内容 tree.write("test_book.xml", encoding="utf-8", xml_declaration=True, pretty_print=True)
内容的提问来源于stack exchange,提问作者Karakorum
相关产品推荐
相关产品推荐

