如何用XPath处理含缺失节点的XML,解决基数错误?
问题翻译
我需要分析一段特殊结构的XML:
<body> <return> <items> <key>name</key> <value>A</value> </items> <items> <key>version</key> <value>1</value> </items> </return> <return> <items> <key>name</key> <value>B</value> </items> </return> </body>
可以看到,部分<return>节点包含对应version的<items/value>节点,部分缺失。我希望用XPath表达式生成如下格式的输出:
Name: A, Version: 1 Name: B, Version: n/a
我尝试过使用map:merge和||拼接,代码如下:
/*/return/items[key="name"]/value/string() ||/*/return/items[key="version"]
但出现了基数错误。请问能否让/*/return/items[key="version"]在节点不存在时返回指定值以消除基数错误?或者有其他解决方案?
解决方案
核心是限定匹配范围到单个<return>节点,避免跨节点匹配导致的数量不匹配问题。
方法1:XPath 3.0+ 表达式(推荐)
用for循环遍历每个<return>,对单个节点单独提取name和version,缺失时返回n/a:
for $r in /*/return return concat( 'Name: ', $r/items[key="name"]/value/string(), ', Version: ', if ($r/items[key="version"]) then $r/items[key="version"]/value/string() else 'n/a' )
该表达式会为每个<return>生成一行结果,完全匹配需求,同时彻底避免基数错误——每次仅处理一个节点,name和version的匹配范围被严格限定在当前节点内。
方法2:简化基数兼容写法
若环境支持string()的空值处理,可结合条件判断补充默认值:
/*/return/concat( 'Name: ', string(items[key="name"]/value), ', Version: ', string(items[key="version"]/value) || (empty(items[key="version"]) ? 'n/a' : '') )
string()在节点不存在时返回空字符串,再通过条件判断补充n/a,同样能实现需求。
原代码报错原因
原表达式直接拼接所有name值和所有version值,当name的数量(2个)与version的数量(1个)不相等时,触发XPath的基数校验错误——拼接操作要求两个序列长度一致,或其中一个为单值。
内容的提问来源于stack exchange,提问作者iPinky7
相关产品推荐
相关产品推荐

