如何选择以下同胞,直到某个同胞

时间:2018-07-03 15:07:51

标签: xpath xquery

我目前正在使用已使用自定义xml转换器转换为xml的VDA消息类型。但是,源文档中的每个标题和行记录都处于同一级别,如下例所示:

<root>
    <row>
        <Record_type>512</Record_type>
        <Customer_item_Number>A0528406</Customer_item_Number>
        <Supplier_item_number>10962915</Supplier_item_number>
    </row>
    <row>
        <Record_type>513</Record_type>
        <Date>170306</Date>
        <Quantity>115</Quantity>
    </row>
    <row>
        <Record_type>513</Record_type>
        <Date>190306</Date>
        <Quantity>97</Quantity>
    </row>
    <row>
        <Record_type>512</Record_type>
        <Customer_item_Number>A0528433</Customer_item_Number>
        <Supplier_item_number>10962916</Supplier_item_number>
    </row>
    <row>
        <Record_type>513</Record_type>
        <Date>170306</Date>
        <Quantity>115</Quantity>
    </row>
    <row>
        <Record_type>513</Record_type>
        <Date>170306</Date>
        <Quantity>115</Quantity>
    </row>
    <row>
        <Record_type>513</Record_type>
        <Date>170306</Date>
        <Quantity>115</Quantity>
    </row>
    <row>
        <Record_type>513</Record_type>
        <Date>170306</Date>
        <Quantity>115</Quantity>
    </row>
</root>

(512)条记录类型是标题,以下(513)条记录类型是其上方的(512)条记录的行。

我正在努力格式化此消息,以便在每个标头(512)记录下方缩进行(513)。

即所需的输出,像这样。

<root>
    <Header>
        <Record_type>512</Record_type>
        <Customer_item_Number>A0528406</Customer_item_Number>
        <Supplier_item_number>10962915</Supplier_item_number>
        <Line>
            <Record_type>513</Record_type>
            <Date>170306</Date>
            <Quantity>115</Quantity>
        </Line>
        <Line>
            <Record_type>513</Record_type>
            <Date>190306</Date>
            <Quantity>97</Quantity>
        </Line>
    </Header>
    <Header>
        <Record_type>512</Record_type>
        <Customer_item_Number>A0528433</Customer_item_Number>
        <Supplier_item_number>10962916</Supplier_item_number>
        <Line>
            <Record_type>513</Record_type>
            <Date>170306</Date>
            <Quantity>115</Quantity>
        </Line>
        <Line>
            <Record_type>513</Record_type>
            <Date>170306</Date>
            <Quantity>115</Quantity>
        </Line>
        <Line>
            <Record_type>513</Record_type>
            <Date>170306</Date>
            <Quantity>115</Quantity>
        </Line>
        <Line>
            <Record_type>513</Record_type>
            <Date>170306</Date>
            <Quantity>115</Quantity>
        </Line>
    </Header>
</root>

我使用以下兄弟姐妹取得了一些成功,但是我无法将其与先前的兄弟姐妹联系起来,仅在下一个循环之前过滤掉所需的记录。

我希望有人能够提供帮助。 :)

3 个答案:

答案 0 :(得分:1)

在XQuery 3.1中,您可以使用翻滚窗口https://www.w3.org/TR/xquery-31/#id-tumbling-windows

<root>
{    
for tumbling window $record in root/row
start $s when $s/Record_type = 512
return
    <Header>
        {
            head($record)/*,
            tail($record) !
                <Line>
                    { * }
                </Line>
        }
    </Header>
}
</root>

https://xqueryfiddle.liberty-development.net/gWcDMef

答案 1 :(得分:1)

如果您的XQuery处理器支持 XQuery 3.0 window clauses,则您的查询(至少在概念上)非常简单有效:

foreach ($xml->xpath('//ReturnValues') as $item) {

否则,您必须使用<root>{ for tumbling window $w in /root/row start when true() end next $n when $n/Record_type = '512' return <Header>{ head($w)/*, for $line in tail($w) return <Line>{$line/*}</Line> }</Header> }</root> preceding-sibling XPath轴,就像Mads Hansen在他的回答中所示:

following-sibling

在这里,我们首先获取当前标头之后的所有行,然后检查每一行是否在它之前的最后一个标头是当前行。在这里重要的是使用<root>{ for $header in /root/row[Record_type = '512'] return <Header>{ $header/*, for $line in $header/following-sibling::row[Record_type = '513'] let $prev-headers := $line/preceding-sibling::row[Record_type = '512'] where $prev-headers[last()] is $header return <Line>{$line/*}</Line> }</Header> }</root> 而不是is=,因为后两者仅在原子项上起作用。这意味着在执行比较之前,XML节点已被原子化(即被精简为仅其连接的文本内容)。 eq运算符会比较节点身份

答案 2 :(得分:0)

对于每个rowRecord_type的{​​{1}},创建一个512元素。

为了找到相关的Header组元素的row个元素,您想从512位{{ 1}},谁是第一个Line是当前标题。

row