如何用xmlstarlet与XPath同时提取XML元素及属性值?
用xmlstarlet同时提取对应XML节点与属性值的方法
XML结构
root +- foo +- bar | +- @baz
需求
我需要在命令行一次性提取/root/foo的文本值和/root/bar/@baz的属性值,并且让每一组对应的值显示在同一行。
已尝试的命令及问题
有效但拆分的命令
分别执行以下命令可以单独获取对应值,但无法合并为每行一组的格式:
cat file.xml | xmlstarlet sel -t -v "/root/foo" -n
返回结果:
Value F1 Value F2
cat file.xml | xmlstarlet sel -t -v "/root/bar/@baz" -n
返回结果:
Value B1 Value B2
无效命令1
尝试用XPath或表达式合并,但仅返回foo的值:
cat file.xml | xmlstarlet sel -t -v "/root/foo|bar/@baz" -n
返回结果:
Value F1 Value F2
无效命令2
尝试用逻辑表达式筛选,直接编译报错:
cat file.xml | xmlstarlet sel -t -v "/root/[foo and bar/@baz]" -n
报错信息:
compilation error: element with-param XSLT-with-param: Failed to compile select expression '/root/[foo and bar/@baz]'
更新:最小可复现示例
XML文件内容
<root> <foo>Value F1</foo> <bar baz="Value B1" /> <foo>Value F2</foo> <bar baz="Value B2" /> </root>
期望输出
Value F1 Value B1 Value F2 Value B2
使用的xmlstarlet版本
1.6.1 compiled against libxml2 2.9.13, linked with 20913 compiled against libxslt 1.1.35, linked with 10135
解决方案
可以通过匹配节点位置的方式,将对应位置的foo和bar/@baz值拼接输出,使用以下命令:
xmlstarlet sel -t -m "/root/foo" -v "." -o " " -v "../bar[position()=current()/position()]/@baz" -n file.xml
或者用concat函数简化:
xmlstarlet sel -t -m "/root/foo" -v "concat(., ' ', ../bar[position()=position()]/@baz)" -n file.xml
命令说明
-m "/root/foo":遍历每个foo节点-v ".":输出当前foo节点的文本值-o " ":输出分隔空格-v "../bar[position()=current()/position()]/@baz":输出与当前foo同位置的bar节点的baz属性值-n:每组值输出后换行
执行上述命令后,即可得到期望的每行一组的输出格式。
内容的提问来源于stack exchange,提问作者Vihung
相关产品推荐
相关产品推荐

