存在xmlns属性时如何使用XmlStarlet原地修改XML文件
问题根因
你的XML根节点<widget>声明了默认命名空间xmlns="http://www.w3.org/ns/widgets",该命名空间下的所有元素在XPath查询时必须绑定对应命名空间前缀才能被匹配到。你之前的命令里XPath写的//widget只会匹配无命名空间的widget元素,自然找不到目标节点;之前尝试-N参数没生效,基本都是因为绑定前缀后没有在XPath路径中给元素名加对应前缀,或是填写的命名空间URI和XML中声明的不一致。
当你删掉xmlns属性后,widget元素变为无命名空间元素,原命令自然可以正常运行。
正确修改命令
首先通过-N参数给默认命名空间绑定一个自定义前缀(前缀名可任意定义,只要和XPath中使用的一致即可),再在XPath中给widget元素加上该前缀即可。
单属性修改(以id为例)
xmlstarlet edit --inplace \ -N w="http://www.w3.org/ns/widgets" \ --update "//w:widget/@id" \ --value "$1" config.xml
注意给$1加上双引号,避免传入值包含空格、特殊字符时出现解析错误。
一次性修改四个属性
可以把多个更新规则写到同一条命令中,通过位置参数分别传入四个属性的目标值即可:
xmlstarlet edit --inplace \ -N w="http://www.w3.org/ns/widgets" \ --update "//w:widget/@id" --value "$1" \ --update "//w:widget/@android-version" --value "$2" \ --update "//w:widget/@ios-version" --value "$3" \ --update "//w:widget/@version" --value "$4" \ config.xml
注意事项
- 这里的
android-version、ios-version都是无前缀的普通属性,不属于xmlns:android声明的命名空间,不需要加android前缀匹配;只有属性名前带android:前缀的属性(比如android:versionCode)才属于android命名空间,匹配时需要额外绑定android命名空间前缀。 - 绑定命名空间时填写的URI必须和XML中声明的完全一致,错漏字符都会导致匹配失败。
内容的提问来源于stack exchange,提问作者Mert Alnuaimi
相关产品推荐
相关产品推荐

