XPath 1.0实现:匹配兄弟元素DBIT时为Amt值添加负号
解决XPath 1.0中根据兄弟节点值为Amt添加负号的问题
问题分析
你遇到的string-length() cardinality错误,是因为XPath 1.0中string-length()要求参数是单个字符串,但你传入了节点集(比如直接用../CdtDbtInd[.='DBIT'])。当节点集包含多个节点(哪怕逻辑上应该只有一个),或者未被转成字符串时,就会触发这个错误。
示例XML
基于你的需求给出典型的XML结构:
<Transactions> <Transaction> <Amt Ccy="EUR">250.50</Amt> <CdtDbtInd>CRDT</CdtDbtInd> </Transaction> <Transaction> <Amt Ccy="EUR">100.00</Amt> <CdtDbtInd>DBIT</CdtDbtInd> </Transaction> <Transaction> <Amt Ccy="GBP">75.25</Amt> <CdtDbtInd>DBIT</CdtDbtInd> </Transaction> </Transactions>
正确的XPath表达式
使用修正后的Becker方法,确保每次处理单个节点并将布尔判断转为数字:
//Amt[@Ccy="EUR"]/concat( substring('-', 1, number(string(../CdtDbtInd) = 'DBIT')), normalize-space(.) )
表达式拆解
//Amt[@Ccy="EUR"]:定位所有币种为EUR的Amt元素string(../CdtDbtInd) = 'DBIT':将兄弟节点CdtDbtInd转为字符串后,判断是否等于DBIT,返回布尔值number(...):将布尔值转为数字(true=1,false=0)substring('-', 1, 数字):数字为1时取'-',为0时返回空字符串normalize-space(.):去除Amt值前后的空格,保证数值干净
替代写法(更严谨处理节点集)
如果担心兄弟节点CdtDbtInd可能存在多个,可以明确取第一个匹配的节点:
//Amt[@Ccy="EUR"]/concat( substring('-', 1, number(../CdtDbtInd[normalize-space(.)='DBIT'][1])), normalize-space(.) )
针对示例XML,这个表达式会返回符合要求的带符号数值列表:
250.50-100.00
内容的提问来源于stack exchange,提问作者stax
相关产品推荐
相关产品推荐

