Shell环境下解析CMDBuild SOAP XML提取指定数据
刚好我之前处理过类似的CMDBuild旧版SOAP XML数据提取需求,用xmlstarlet或者xmllint这俩Shell工具就能完美解决,下面给你详细的操作步骤和命令:
使用xmlstarlet提取数据
xmlstarlet对带命名空间的XML支持很友好,首先要先声明XML里的命名空间(避免写冗长的URL)。假设你的SOAP响应XML文件名为cmdbuild_response.xml:
提取单个字段(比如instance_id的数值)
运行下面的命令就能直接拿到instance_id对应的value:
xmlstarlet sel -N soap="http://schemas.xmlsoap.org/soap/envelope/" -N ns2="http://soap.services.cmdbuild.org" -t -v "//soap:Envelope/soap:Body/ns2:getCardListResponse/ns2:return/ns2:cards/ns2:attributeList[ns2:name='instance_id']/ns2:value" cmdbuild_response.xml
简单解释下参数:
-N:定义命名空间的别名,后续XPath里直接用别名就行-t:启用模板模式,用来定制输出格式-v:提取指定XPath路径的文本内容- XPath里的
[ns2:name='instance_id']是过滤条件,只匹配name为instance_id的attributeList节点
提取多个字段并格式化输出
如果想一次性提取instance_id、Description、instance_name这三个字段,并且用逗号分隔成一行,可以用这个命令:
xmlstarlet sel -N soap="http://schemas.xmlsoap.org/soap/envelope/" -N ns2="http://soap.services.cmdbuild.org" -t \ -m "//soap:Envelope/soap:Body/ns2:getCardListResponse/ns2:return/ns2:cards" \ -v "ns2:attributeList[ns2:name='instance_id']/ns2:value" -o "," \ -v "ns2:attributeList[ns2:name='Description']/ns2:value" -o "," \ -v "ns2:attributeList[ns2:name='instance_name']/ns2:value" -n \ cmdbuild_response.xml
额外参数说明:
-m:匹配每个cards节点(如果返回多个卡片,会循环处理每一个)-o:输出自定义分隔符(这里用逗号)-n:每处理完一个卡片就换行,让结果更清晰
使用xmllint提取数据
xmllint是libxml2自带的工具,不用额外安装,处理XML也很顺手。
提取单个字段(比如Description的内容)
用local-name()可以避开命名空间前缀的问题,命令更简洁:
xmllint --xpath "//*[local-name()='attributeList'][*[local-name()='name']='Description']/*[local-name()='value']/text()" cmdbuild_response.xml
如果你想用完整的命名空间声明,也可以这么写(需要确保环境能识别命名空间):
xmllint --xpath "//soap:Envelope/soap:Body/ns2:getCardListResponse/ns2:return/ns2:cards/ns2:attributeList[ns2:name='Description']/ns2:value/text()" --xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" --xmlns:ns2="http://soap.services.cmdbuild.org" cmdbuild_response.xml
提取多个字段并格式化
xmllint本身不能直接输出分隔符,所以可以结合awk和sed来整理结果:
xmllint --xpath "//soap:Envelope/soap:Body/ns2:getCardListResponse/ns2:return/ns2:cards/ns2:attributeList[ns2:name='instance_id' or ns2:name='Description' or ns2:name='instance_name']/text()" --xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" --xmlns:ns2="http://soap.services.cmdbuild.org" cmdbuild_response.xml | awk 'NR%2==0{printf "%s,", $0} END{print ""}' | sed 's/,$//'
这个命令的逻辑是:
- 先提取所有目标字段的name和value文本,结果会是每行一个值(比如先出
instance_id,再出它的数值,以此类推) - 用awk筛选出偶数行(也就是对应的value值),并用逗号连接
- 用sed去掉最后一个多余的逗号
内容的提问来源于stack exchange,提问作者user3177303
相关产品推荐
相关产品推荐

