输入xml格式:
a.xml
<Global>
<CurrencyType>INR</CurrencyType>
<Amount>100.56</Amount>
</Global>
b.xml
<Global>
<CurrencyType>USD</CurrencyType>
<Amount>234.45</Amount>
</Global>
c.xml
<Global>
<CurrencyType>INR</CurrencyType>
<Amount>20</Amount>
</Global>
d.xml
<Global>
<CurrencyType>EUR</CurrencyType>
<Amount>450.0</Amount>
</Global>
e.xml
<Global>
<CurrencyType>DIR</CurrencyType>
<Amount>100.56</Amount>
</Global>
我使用cts:sum
查询添加各种货币类型的金额值。除 INR&amp;之外的货币值美元被修改为 OTH ,如下所示:
let $doc := all the xml files
for $currency in fn:distinct-values($doc//CurrencyType)
let $tot := cts:sum(cts:element-values(xs:QName('Amount'),(),(),
cts:element-value-query(xs:QName('Currency'),$currency)))
return if($currency eq ('INR','USD')) then concat($tot, " ", $currency)
else concat($tot, " ", 'OTH')
提供以下输出
120.56 INR
234.45 USD
450.0 OTH
100.0 OTH
现在,我需要总结具有相同货币值的值。我需要添加450.0 + 100.0才能获得其他货币值的总额。
有人可以为此提供帮助吗?
答案 0 :(得分:3)
如Jim和Mads所述,请避免distinct-values
。特别是因为cts:element-values
无论如何都需要范围索引。我也避免使用cts:sum
(顺便说一下,这是正式弃用的),而是使用性能更高的cts:sum-aggregate
。我考虑过吉姆的方法,并做一些像:
let $currencies := cts:values(cts:element-reference(xs:QName("CurrencyType")))
let $explicit-currencies := $currencies[. = ("INR", "USD")]
let $other-currencies := $currencies[not(. = $explicit-currencies)]
return (
for $c in $explicit-currencies
let $sum := cts:sum-aggregate(
cts:element-reference(xs:QName("Amount")),
(),
cts:range-query(cts:element-reference(xs:QName("CurrencyType")), "=", $c)
)
return $c || " " || $sum,
let $other-sum := cts:sum-aggregate(
cts:element-reference(xs:QName("Amount")),
(),
cts:range-query(cts:element-reference(xs:QName("CurrencyType")), "=", $other-currencies)
)
return "OTH" || " " || $other-sum
)
注意:cts:range-query
是MarkLogic 9中的新功能。您可以在旧版本中使用cts:element-range-query
。
你可以进一步缩短上面的代码,并按照Jim的建议完成:
let $explicit-currencies := ("INR", "USD")
return (
for $c in $explicit-currencies
let $sum := cts:sum-aggregate(
cts:element-reference(xs:QName("Amount")),
(),
cts:range-query(cts:element-reference(xs:QName("CurrencyType")), "=", $c)
)
return $c || " " || $sum,
let $other-sum := cts:sum-aggregate(
cts:element-reference(xs:QName("Amount")),
(),
cts:not-query(cts:element-value-query(xs:QName("CurrencyType"), $explicit-currencies))
)
return "OTH" || " " || $other-sum
)
后者不需要CurrencyType
上的范围索引,但如果你将其暴露为方面,那么无论如何你可能都有。
HTH!
答案 1 :(得分:2)
distinct-values()
可能是一个非常昂贵的电话。
对于您的问题,您也不需要它。
只做3个查询 - 一个用于INR,一个用于USD,另一个用于cts:not-query(cts:element-value-query(xs:QName('CurrencyType'), ("INR","USD")))
答案 2 :(得分:2)
取决于多少文档&#34;所有XML文件&#34;是,将所有这些文档和XPath加载到CurrencyType
,使用distinct-values()
可能既昂贵又缓慢。
相反,你可以:
CurrencyType
获取这些文档的Amount
和cts:element-value-co-occurences()
值的明确列表,并将结果作为地图返回。CurrencyType
并将标准化Amount
标签的所有CurrencyType
值相加 (: 1. obtain the CurrencyType and Amount values as a map :)
let $currencyMap := cts:element-value-co-occurrences(
xs:QName("CurrencyType"),
xs:QName("Amount"),
"map",
(:change this to a more specific query for "all the xml files" :)
cts:true-query())
let $totalMap := map:map()
return
(
for $currency in map:keys($currencyMap)
(: 2.a. normalize the labels :)
let $label :=
if ($currency = ('INR', 'USD')) then $currency
else "OTH"
return
(: 2.b. as we iterate through each CurrencyType, add it's Amount to the current total :)
map:put($totalMap, $label,
sum((map:get($currencyMap, $currency), map:get($totalMap, $label))) ),
(: 3. Print out the totals for the consolidated currency labels :)
map:keys($totalMap) ! concat(map:get($totalMap, .), " ", .)
)