我有以下XML
<Item>
<line>1</line>
<itemno>ABC</itemno>
<qty>3</qty>
<serialnos>
<serial>ABC1</serial>
<serial>ABC2</serial>
<serial>ABC3</serial>
</serialnos>
<Trackingnos>
<trno>ABCT1</trno>
<trno>ABCT2</trno>
<trno>ABCT3</trno>
</Trackingnos>
</Item>
现在问题是我已将它们转换为以下格式
<Line>
<opn>ABC</opn>
<qty>3</qty>
<serialCollection>
<serials>
<lineno>1</lineno>
<serial>ABC1</serial>
<trk>ABCT1</trk>
</serials>
<serials>
<lineno>1</lineno>
<serial>ABC2</serial>
<trk>ABCT2</trk>
</serials>
<serials>
<lineno>1</lineno>
<serial>ABC3</serial>
<trk>ABCT3</trk>
</serials>
</serialCollection>
</Line>
我遇到的问题是源xml中的序列号和跟踪号的组合可能会有所不同。 例如: 可以有3个连续出版物,跟踪编号只能是1 要么 可以有3个连续出版物,跟踪编号可以是3 要么 没有连续出版物,跟踪号码可以是3 要么 没有连续出版物,跟踪号可以是2
如果跟踪号和序列号相等,那么我可以一对一分配。 如果跟踪号码小于序列号,那么我必须随机选择最后一个跟踪号并将其分配给剩余的序列号。
如果没有连续剧,则下面是输出
<Line>
<opn>ABC</opn>
<qty>3</qty>
<serialCollection>
<serials>
<lineno>1</lineno>
</serial>
<trk>ABCT1</trk>
</serials>
<serials>
<lineno>1</lineno>
</serial>
<trk>ABCT2</trk>
</serials>
<serials>
<lineno>1</lineno>
</serial>
<trk>ABCT3</trk>
</serials>
</serialCollection>
</Line>
同样,如果没有追踪号码,那么它们就是空的。
我必须在Xquery中进行此转换,但我无法做到这一点。有人可以帮忙吗?
答案 0 :(得分:0)
如果我了解您的要求,则serialCollection
将始终包含等于跟踪号码数量或序列号数量的serial
元素,以较大者为准。您可以使用fn:max
计算,并迭代生成的数字序列以创建正确数量的元素。
接下来,您要选择与序列中位置对应的跟踪编号和序列号,除非该位置的跟踪编号为空,在这种情况下您要选择最后一个跟踪编号。生成包含两个元素的序列并选择序列的第一个项目。如果第一个为空,则将选择第二个。
declare function local:transform(
$item as element(Item)
) as element(Line)
{
element Line {
$item/itemno/element opn { string() },
$item/qty
,
let $tracking-numbers := $item/Trackingnos/trno
let $serial-numbers := $item/serialnos/serial
let $len := max((count($tracking-numbers), count($serial-numbers)))
where ($len gt 0)
return element serialCollection {
for $i in (1 to $len)
return element serials {
$item/line/element lineno { string() },
element serial { $serial-numbers[$i]/string() },
element trk { ($tracking-numbers[$i], $tracking-numbers[last()])[1]/string() }
}
}
}
};