问题是我需要遍历重复节点,但也要从基于LineId进行匹配的同级重复节点中提取信息。如果这是一个数据库,我会将每个重复节点都等同于一个表,并希望根据匹配的ID将两个表的联接放出来。
我首先将“根目录” /“货件” /“货件” /“容器” /“容器”循环到“文档” /“页眉/详细信息”,这似乎可行,因为我想为源中的每个“容器”创建1条记录作为目标中的1条“详细记录” 。但是,当我从“根” /“货件” /“货件” /“细节” /“细节”中映射字段时,我仅从映射的第一条记录中获取了数据,而不是具有匹配的LineId的记录。然后,我尝试将Root / Shipments / Shipment / Details / Detail添加到循环中,并有条件地抑制其中节点之间LineId不匹配但行不通的Document / Detail。因此,我尝试在具有相同抑制条件的Detail上添加第二个循环,但该循环也不起作用。然后,我想我会尝试使用XSLT模板基于LineId作为输入来“查找” Root / Shipments / Shipment / Details / Detail中的数据,但它从未返回任何数据(始终为空)。另外,要在字段级别分别获取每个字段,我需要搜索X次,而我需要映射的每个字段需要搜索1次,而不是每条记录1次,因此这似乎效率也不高。
我的XSLT知识有限。如果可能的话,我宁愿使用具有脚本功能的Mapping,而不是纯XSLT。性能也将是一个问题,因为在该项目中我需要处理的文件数量很高。我在下面提供的示例是我需要处理的数十个字段的精简版本,源文件在层次结构中具有更多层。
实现我需要做的最好的方法是什么?
源文件:
<Root>
<Shipments>
<Shipment>
<ShipId>1</ShipId>
<Details>
<Detail>
<LineId>1</LineId>
<RequestedQty>10</RequestedQty>
<Sku>347</Sku>
<Status>C</Status>
</Detail>
<Detail>
<LineId>2</LineId>
<RequestedQty>5</RequestedQty>
<Sku>125</Sku>
<Status>P</Status>
</Detail>
<Detail>
<LineId>3</LineId>
<RequestedQty>8</RequestedQty>
<Sku>337</Sku>
<Status>O</Status>
</Detail>
<Detail>
<LineId>4</LineId>
<RequestedQty>12</RequestedQty>
<Sku>7438</Sku>
<Status>C</Status>
</Detail>
</Details>
<Containers>
<Container>
<ContainerId>1</ContainerId>
<Details>
<Detail>
<LineId>1</LineId>
<Lot>103</Lot>
<ShipQty>10</ShipQty>
</Detail>
<Detail>
<LineId>2</LineId>
<Lot>102</Lot>
<ShipQty>3</ShipQty>
</Detail>
</Details>
<TrackingNUmber>Z934793498923984</TrackingNUmber>
</Container>
<Container>
<ContainerId>2</ContainerId>
<Details>
<Detail>
<LineId>4</LineId>
<Lot>101</Lot>
<ShipQty>10</ShipQty>
</Detail>
<Detail>
<LineId>4</LineId>
<Lot>105</Lot>
<ShipQty>2</ShipQty>
</Detail>
</Detail>
</Details>
<TrackingNUmber>Z531365161663161</TrackingNUmber>
</Container>
</Containers>
</Shipment>
</Shipments>
</Root>
进入:
<Document>
<Header>
<ShipId>1</ShipId>
<Detail>
<ContainerId>1</ContainerId>
<LineId>1</LineId>
<Lot>103</Lot>
<ShipQty>10</ShipQty>
<RequestedQty>10</RequestedQty>
<Sku>347</Sku>
<Status>C</Status>
<TrackingNUmber>Z934793498923984</TrackingNUmber>
</Detail>
<Detail>
<ContainerId>1</ContainerId>
<LineId>2</LineId>
<Lot>102</Lot>
<ShipQty>3</ShipQty>
<RequestedQty>5</RequestedQty>
<Sku>125</Sku>
<Status>P</Status>
<TrackingNUmber>Z934793498923984</TrackingNUmber>
</Detail>
<Detail>
<ContainerId>2</ContainerId>
<LineId>4</LineId>
<Lot>101</Lot>
<ShipQty>10</ShipQty>
<RequestedQty>12</RequestedQty>
<Sku>7438</Sku>
<Status>C</Status>
<TrackingNUmber>Z531365161663161</TrackingNUmber>
</Detail>
<Detail>
<ContainerId>2</ContainerId>
<LineId>4</LineId>
<Lot>105</Lot>
<ShipQty>2</ShipQty>
<RequestedQty>12</RequestedQty>
<Sku>7438</Sku>
<Status>C</Status>
<TrackingNUmber>Z531365161663161</TrackingNUmber>
</Detail>
</Header>
</Document>
答案 0 :(得分:0)
我不确定这是最好的解决方案,但我有一些可能会帮助您解决问题。这个想法是使用脚本功能在目标文档中创建Detail-element。
鉴于您有很多元素,建议您使用以下内容来正确命名:
“验证图”以获取xslt。复制Detail-element及其内容。
删除所有到Detail元素的直接链接。
在源Container / Details / Detail和目标Detail之间添加一个循环的functoid。
添加脚本功能,将其连接到目标Detail。选择“内联XSLT”,然后粘贴您在步骤2中复制的代码。
测试地图,以验证其大部分功能是否正确(尽管“运货/详细信息/详细信息”仍然是错误的)
修改脚本功能中的xslt。您希望变量指向与当前行相对应的Shipment / Details / Detail元素。
根据当前LineId设置变量:
<xsl:variable name="CurrentShipmentDetail" select="../../../../Details/Detail[LineId=current()/LineId]"/>
之前:
<RequestedQty>
<xsl:value-of select="../../../../Details/Detail/RequestedQty/text()" />
</RequestedQty>
之后:
<RequestedQty>
<xsl:value-of select="$CurrentShipmentDetail/RequestedQty/text()" />
</RequestedQty>
完整地图:
以及完整的xslt代码:
<Detail>
<ContainerId>
<xsl:value-of select="../../ContainerId/text()" />
</ContainerId>
<LineId>
<xsl:value-of select="LineId/text()" />
</LineId>
<Lot>
<xsl:value-of select="Lot/text()" />
</Lot>
<ShipQty>
<xsl:value-of select="ShipQty/text()" />
</ShipQty>
<xsl:variable name="CurrentShipmentDetail" select="../../../../Details/Detail[LineId=current()/LineId]"/>
<RequestedQty>
<xsl:value-of select="$CurrentShipmentDetail/RequestedQty/text()" />
</RequestedQty>
<Sku>
<xsl:value-of select="$CurrentShipmentDetail/Sku/text()" />
</Sku>
<Status>
<xsl:value-of select="$CurrentShipmentDetail/Status/text()" />
</Status>
<TrackingNUmber>
<xsl:value-of select="../../TrackingNUmber/text()" />
</TrackingNUmber>
</Detail>
答案 1 :(得分:0)
您应该可以使用循环和等曲函数来做到这一点。
将货件/详细信息连接到循环功能,然后将容器/详细信息连接到相同的循环功能。
然后将Shipment // LineId和Container // LindId连接到相等的功能,然后将相等功能的功能连接到目标细节。
您将看到Mapper如何在xsl中构建循环和条件。您可以从那里进行调整。