如何阻止xmllint移除XML文件中的空白字符?
问题
之前已经能用xmllint批量修改XML文件中的指定属性,但这些文件存在大量冗余空白字符,xmllint会将其全部清理,导致git diff中出现多达50行修改,难以分辨功能性差异。有没有办法让xmllint仅修改目标属性值,同时保留原有空白格式?(已查阅xmllint手册,未找到对应选项)
示例
原始XML文件
<target_tags> <target_tag name="my_tag1" default="old_value1" /> <target_tag name="my_tag2" default="old_value2" /> <target_tag name="my_tag3" default="old_value3" /> </target_tags>
执行的xmllint命令
xmllint --shell /tmp/tmp.xml << EOF cd //target_tag[@name="my_tag1"]/@default set new_value save bye EOF
修改后的XML文件
<target_tags> <target_tag name="my_tag1" default="new_value"/> <target_tag name="my_tag2" default="old_value2"/> <target_tag name="my_tag3" default="old_value3"/> </target_tags>
解决方案
xmllint基于libxml2实现,其核心逻辑会强制规范XML结构,无法做到仅修改属性而完全保留原始空白和格式。推荐使用以下两种替代方案:
1. xmlstarlet(推荐,适用于所有XML场景)
xmlstarlet支持在修改XML时默认保留原始格式(除非主动指定格式化参数)。安装后执行以下命令即可完成修改:
xmlstarlet edit --inplace \ --update "//target_tag[@name='my_tag1']/@default" \ --value "new_value" \ /tmp/tmp.xml
该命令仅会修改目标属性值,原始的换行、缩进、标签结尾空格等格式都会完整保留。
2. sed(仅适用于结构简单的XML)
如果你的XML结构固定(属性顺序不变、无跨换行的属性定义),可以用sed直接做文本替换,避免XML解析带来的格式变更:
sed -i 's/\(<target_tag name="my_tag1" default="\)[^"]*"/\1new_value"/' /tmp/tmp.xml
注意:这种方法有局限性,若XML结构出现属性顺序调整、属性跨行等情况,sed会失效,仅建议用于简单场景。
内容的提问来源于stack exchange,提问作者Will1v
相关产品推荐
相关产品推荐

