XQuery 构造具有顺序祖先节点名称的字符串对象
XQuery constructs string object with sequential ancestor node names
a.xml
:
<execution xmlns="http://www.example.org">
<header>
<messageId>FX123</messageId>
</header>
<isCorrection>false</isCorrection>
<trade>
<tradeHeader>
<partyTradeIdentifier>
<partyReference href="ptyA"/>
<tradeId>12345</tradeId>
</partyTradeIdentifier>
<tradeDate>2019-12-21</tradeDate>
</tradeHeader>
<fxTargetKnockoutForward>
<target>
<accumulationRegion>
<lowerBound>
<condition>AtOrAbove</condition>
</lowerBound>
<upperBound>
<condition>Below</condition>
</upperBound>
</accumulationRegion>
<accumulationRegion>
<lowerBound>
<condition>AtOrAbove</condition>
<initialValue>1.1000</initialValue>
</lowerBound>
<multiplier>2</multiplier>
</accumulationRegion>
<knockoutLevel>
<amount>
<currency>CAD</currency>
<amount>100000.00</amount>
</amount>
<targetStyle>Exact</targetStyle>
</knockoutLevel>
</target>
<expirySchedule>
<adjustedDate>2019-12-23</adjustedDate>
<adjustedDate>2020-01-27</adjustedDate>
<adjustedDate>2020-02-25</adjustedDate>
<adjustedDate>2020-03-26</adjustedDate>
</expirySchedule>
<settlementSchedule>
<dateAdjustments>
<businessDayConvention>FOLLOWING</businessDayConvention>
<businessCenters>
<businessCenter>CATO</businessCenter>
<businessCenter>USNY</businessCenter>
</businessCenters>
</dateAdjustments>
<adjustedDate>2019-12-24</adjustedDate>
<adjustedDate>2020-01-28</adjustedDate>
<adjustedDate>2020-02-26</adjustedDate>
<adjustedDate>2020-03-27</adjustedDate>
</settlementSchedule>
<fixingInformationSource>
<rateSource>Reuters</rateSource>
<rateSourcePage>WMRSPOT09</rateSourcePage>
</fixingInformationSource>
</fxTargetKnockoutForward>
</trade>
</execution>
Logic: I pass in-memory XML (a.xml
) and targeted element (“trade”
) as parameters -> the function local:array-qname
evaluates all of this element’s descendants -> Whenever the descendant’s node name is the same as its sibling’s node name, it is considered a candidate -> the function walks backwards to retrieve all of its ancestor node name (except the root node) up to the passed element (“trade”
) level.
The desired result: string array objects, of each object contains all of the candidate's sequential ancestor node names and its own node name. The expected result is:
( ("trade","fxTargetKnockoutForward","target","accumulationRegion"),
("trade","fxTargetKnockoutForward","expirySchedule","adjustedDate"),
("trade","fxTargetKnockoutForward","settlementSchedule","dateAdjustments","businessCenters","businessCenter"),
("trade","fxTargetKnockoutForward","settlementSchedule","adjustedDate") )
库模块是:
xquery version "1.0-ml";
declare function local:array-qname(
$doc as node()*,
$element as xs:string
) as xs:string*
{
let $e := $doc//*[name() = $element]
for $d in $e/descendant::*[name() = name(following-sibling::*[1])],
$a in $d/ancestor::*[not(name() = name($doc/*))]/name(.)
return
for $_ in $a
return
<a>
( {xs:QName($a)},{xs:QName(local-name($d))} )
</a>
};
let $doc := doc("a.xml")
return
local:array-qname($doc, "trade")
但是出了问题:
(trade,fxTargetKnockoutForward,target,accumulationRegion),
(trade,fxTargetKnockoutForward,expirySchedule,adjustedDate),
(trade,fxTargetKnockoutForward,settlementSchedule,dateAdjustments,businessCenters,businessCenter),
(trade,fxTargetKnockoutForward,settlementSchedule,adjustedDate),
如何让我的模块工作?
有
declare variable $element-name as xs:QName external := QName('http://www.example.org', 'trade');
let $base := //*[node-name() = $element-name]
for $d in $base//*[node-name() = following-sibling::*[1]/node-name()]
return
'('
|| $element-name
|| ': ('
|| ($d/ancestor-or-self::* except $d/ancestor::*[node-name() = $element-name]/ancestor-or-self::*)/node-name() => string-join(', ')
|| '))'
我明白了
(trade: (fxTargetKnockoutForward, target, accumulationRegion))
(trade: (fxTargetKnockoutForward, expirySchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, expirySchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, expirySchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, settlementSchedule, dateAdjustments, businessCenters, businessCenter))
(trade: (fxTargetKnockoutForward, settlementSchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, settlementSchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, settlementSchedule, adjustedDate))
我不确定你的描述“只要后代的节点名称与其兄弟的节点名称相同,它就被认为是候选者 -> 函数向后遍历以检索其所有祖先节点名称(根节点除外)节点)到传递的元素(“交易”)级别。”为什么重复 adjustedDate
不在您想要的输出中,因为样本似乎包含满足条件的该名称的各种元素。
以下解决方案符合要求……
declare function local:array-qname(
$doc as document-node(),
$name as xs:string
) {
for $e in $doc//*[name() = $name]
for $d in $e/descendant::*[name() = name(following-sibling::*[1])]
return <a>{
for $name in $d/ancestor-or-self::*[not(. << $e)]
return node-name($name)
}</a>
};
let $doc := doc('a.xml')
return local:array-qname($doc, 'trade')
…但它与预期的输出不同,因为它会产生重复的路径。如果要避免重复,并且字符串表示就足够了,可以使用distinct-values
:
distinct-values(
for $e in $doc//*[name() = $name]
for $d in $e/descendant::*[name() = name(following-sibling::*[1])]
return string-join($d/ancestor-or-self::*[not(. << $e)]/name(), ' ')
)
a.xml
:
<execution xmlns="http://www.example.org">
<header>
<messageId>FX123</messageId>
</header>
<isCorrection>false</isCorrection>
<trade>
<tradeHeader>
<partyTradeIdentifier>
<partyReference href="ptyA"/>
<tradeId>12345</tradeId>
</partyTradeIdentifier>
<tradeDate>2019-12-21</tradeDate>
</tradeHeader>
<fxTargetKnockoutForward>
<target>
<accumulationRegion>
<lowerBound>
<condition>AtOrAbove</condition>
</lowerBound>
<upperBound>
<condition>Below</condition>
</upperBound>
</accumulationRegion>
<accumulationRegion>
<lowerBound>
<condition>AtOrAbove</condition>
<initialValue>1.1000</initialValue>
</lowerBound>
<multiplier>2</multiplier>
</accumulationRegion>
<knockoutLevel>
<amount>
<currency>CAD</currency>
<amount>100000.00</amount>
</amount>
<targetStyle>Exact</targetStyle>
</knockoutLevel>
</target>
<expirySchedule>
<adjustedDate>2019-12-23</adjustedDate>
<adjustedDate>2020-01-27</adjustedDate>
<adjustedDate>2020-02-25</adjustedDate>
<adjustedDate>2020-03-26</adjustedDate>
</expirySchedule>
<settlementSchedule>
<dateAdjustments>
<businessDayConvention>FOLLOWING</businessDayConvention>
<businessCenters>
<businessCenter>CATO</businessCenter>
<businessCenter>USNY</businessCenter>
</businessCenters>
</dateAdjustments>
<adjustedDate>2019-12-24</adjustedDate>
<adjustedDate>2020-01-28</adjustedDate>
<adjustedDate>2020-02-26</adjustedDate>
<adjustedDate>2020-03-27</adjustedDate>
</settlementSchedule>
<fixingInformationSource>
<rateSource>Reuters</rateSource>
<rateSourcePage>WMRSPOT09</rateSourcePage>
</fixingInformationSource>
</fxTargetKnockoutForward>
</trade>
</execution>
Logic: I pass in-memory XML (
a.xml
) and targeted element (“trade”
) as parameters -> the functionlocal:array-qname
evaluates all of this element’s descendants -> Whenever the descendant’s node name is the same as its sibling’s node name, it is considered a candidate -> the function walks backwards to retrieve all of its ancestor node name (except the root node) up to the passed element (“trade”
) level.
The desired result: string array objects, of each object contains all of the candidate's sequential ancestor node names and its own node name. The expected result is:
( ("trade","fxTargetKnockoutForward","target","accumulationRegion"),
("trade","fxTargetKnockoutForward","expirySchedule","adjustedDate"),
("trade","fxTargetKnockoutForward","settlementSchedule","dateAdjustments","businessCenters","businessCenter"),
("trade","fxTargetKnockoutForward","settlementSchedule","adjustedDate") )
库模块是:
xquery version "1.0-ml";
declare function local:array-qname(
$doc as node()*,
$element as xs:string
) as xs:string*
{
let $e := $doc//*[name() = $element]
for $d in $e/descendant::*[name() = name(following-sibling::*[1])],
$a in $d/ancestor::*[not(name() = name($doc/*))]/name(.)
return
for $_ in $a
return
<a>
( {xs:QName($a)},{xs:QName(local-name($d))} )
</a>
};
let $doc := doc("a.xml")
return
local:array-qname($doc, "trade")
但是出了问题:
(trade,fxTargetKnockoutForward,target,accumulationRegion),
(trade,fxTargetKnockoutForward,expirySchedule,adjustedDate),
(trade,fxTargetKnockoutForward,settlementSchedule,dateAdjustments,businessCenters,businessCenter),
(trade,fxTargetKnockoutForward,settlementSchedule,adjustedDate),
如何让我的模块工作?
有
declare variable $element-name as xs:QName external := QName('http://www.example.org', 'trade');
let $base := //*[node-name() = $element-name]
for $d in $base//*[node-name() = following-sibling::*[1]/node-name()]
return
'('
|| $element-name
|| ': ('
|| ($d/ancestor-or-self::* except $d/ancestor::*[node-name() = $element-name]/ancestor-or-self::*)/node-name() => string-join(', ')
|| '))'
我明白了
(trade: (fxTargetKnockoutForward, target, accumulationRegion))
(trade: (fxTargetKnockoutForward, expirySchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, expirySchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, expirySchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, settlementSchedule, dateAdjustments, businessCenters, businessCenter))
(trade: (fxTargetKnockoutForward, settlementSchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, settlementSchedule, adjustedDate))
(trade: (fxTargetKnockoutForward, settlementSchedule, adjustedDate))
我不确定你的描述“只要后代的节点名称与其兄弟的节点名称相同,它就被认为是候选者 -> 函数向后遍历以检索其所有祖先节点名称(根节点除外)节点)到传递的元素(“交易”)级别。”为什么重复 adjustedDate
不在您想要的输出中,因为样本似乎包含满足条件的该名称的各种元素。
以下解决方案符合要求……
declare function local:array-qname(
$doc as document-node(),
$name as xs:string
) {
for $e in $doc//*[name() = $name]
for $d in $e/descendant::*[name() = name(following-sibling::*[1])]
return <a>{
for $name in $d/ancestor-or-self::*[not(. << $e)]
return node-name($name)
}</a>
};
let $doc := doc('a.xml')
return local:array-qname($doc, 'trade')
…但它与预期的输出不同,因为它会产生重复的路径。如果要避免重复,并且字符串表示就足够了,可以使用distinct-values
:
distinct-values(
for $e in $doc//*[name() = $name]
for $d in $e/descendant::*[name() = name(following-sibling::*[1])]
return string-join($d/ancestor-or-self::*[not(. << $e)]/name(), ' ')
)