首页 > 解决方案 > Xpath:根据兄弟元素中的最大值读取一个值

问题描述

我正在努力阅读

Item/PriceAndTax/PriceComponents[TypeCode = "TAX"]/Rate/DecimalValue

从项目的价值

Item/PriceAndTax/PriceComponents[TypeCode = "UPRICE"]/Rate/DecimalValue 

是最高的。在下面的示例 XML 中,正确的结果是 10.0。在项目 ID 20 中,UPRICE 最高,该项目的 TAX 值为 10.0。

一个想法是根据 /PriceComponents[TypeCode = "UPRICE"]/Rate/DecimalValue 的最高值对项目进行排序,然后从第一个(或最后一个)项目中读取。

我设法进行(降序)排序,但我不知道如何从第一项中读取值:

//Item => sort((),function($item){ $item/PriceAndTax/PriceComponents[TypeCode="UPRICE"]/Rate/DecimalValue }) => reverse()

第二种方法是尝试使用 max 函数比较 Item/PriceAndTax/PriceComponents[TypeCode="UPRICE"]/Rate/DecimalValue 中的值以获取具有最高“UPRICE”值的项目,然后读取 /PriceComponents[TypeCode ="TAX"]/Rate/DecimalValue 来自该项目。

非工作尝试:

//Item/PriceAndTax/PriceComponents[TypeCode="TAX" and Rate/DecimalValue = max(../PriceAndTax/PriceComponents[TypeCode="UPRICE"]/Rate/DecimalValue)]/Rate/DecimalValue/text()

源 XML:

<Invoice>
    <ID>TEST_INVOICE_123</ID>
    <Buyer>
        <ID>CUSTOMER_01</ID>
    </Buyer>
    <Item>
        <ID>10</ID>
        <Quantity>
            <Quantity>2.0</Quantity>
        </Quantity>
        <Product>
            <InternalID>PROD0100</InternalID>
        </Product>
        <PriceAndTax>
            <NetAmount currencyCode="EUR">50.00</NetAmount>
            <PriceComponents>
                <TypeCode>UPRICE</TypeCode>
                <Rate>
                    <DecimalValue>25.00</DecimalValue>
                </Rate>
            </PriceComponents>
            <PriceComponents>
                <TypeCode>TAX</TypeCode>
                <Rate>
                    <DecimalValue>24.0</DecimalValue>
                </Rate>
            </PriceComponents>
        </PriceAndTax>
    </Item>
    <Item>
        <ID>20</ID>
        <Quantity>
            <Quantity>2.0</Quantity>
        </Quantity>
        <Product>
            <InternalID>PROD0200</InternalID>
        </Product>
        <PriceAndTax>
            <NetAmount currencyCode="EUR">105.00</NetAmount>
            <PriceComponents>
                <TypeCode>UPRICE</TypeCode>
                <Rate>
                    <DecimalValue>52.50</DecimalValue>
                </Rate>
            </PriceComponents>
            <PriceComponents>
                <TypeCode>TAX</TypeCode>
                <Rate>
                    <DecimalValue>10.0</DecimalValue>
                </Rate>
            </PriceComponents>
        </PriceAndTax>
    </Item>
    <Item>
        <ID>30</ID>
        <Quantity>
            <Quantity>4.0</Quantity>
        </Quantity>
        <Product>
            <InternalID>PROD0300</InternalID>
        </Product>
        <PriceAndTax>
            <NetAmount currencyCode="EUR">120.00</NetAmount>
            <PriceComponents>
                <TypeCode>UPRICE</TypeCode>
                <Rate>
                    <DecimalValue>30.00</DecimalValue>
                </Rate>
            </PriceComponents>
            <PriceComponents>
                <TypeCode>TAX</TypeCode>
                <Rate>
                    <DecimalValue>14.0</DecimalValue>
                </Rate>
            </PriceComponents>
        </PriceAndTax>
    </Item>
</Invoice>

我使用的工具支持 Xpath 3.1。

提前感谢您的帮助!

文学学士

标签: xpathsaxon

解决方案


撒克逊对此有一个扩展,我多年来一直在尝试进入标准:

saxon:highest(Item/PriceAndTax, 
    function($pt){
       $pt/PriceComponents[TypeCode = "UPRICE"]/Rate/DecimalValue
    }) 
/PriceComponents[TypeCode = "TAX"]/Rate/DecimalValue 

如果你不能使用扩展,那么你可以自己写:见https://www.w3.org/TR/xpath-functions-31/#highest-lowest(在纯 XPath 中比在XSLT,但它可以做到)。

最简单的方法可能是根据 fn:sort 定义最高()函数:

let $highest := function($SEQ, $KEY){fn:sort($SEQ, (), $KEY)[last()]}
return $highest(Item/PriceAndTax, 
    function($pt){
       $pt/PriceComponents[TypeCode = "UPRICE"]/Rate/DecimalValue
    })/PriceComponents[TypeCode = "TAX"]/Rate/DecimalValue 

注意:如果查询不是模式感知的,那么您应该将 DecimalValue 转换为xs:decimal“手动”以确保进行数字比较。


推荐阅读