如何通过使用BizTalk映射器将2个不同的重复节点合并为1个重复节点来进行映射

时间:2018-08-09 23:31:15

标签: join mapping nodes biztalk repeat

问题是我需要遍历重复节点,但也要从基于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>

2 个答案:

答案 0 :(得分:0)

我不确定这是最好的解决方案,但我有一些可能会帮助您解决问题。这个想法是使用脚本功能在目标文档中创建Detail-element。

鉴于您有很多元素,建议您使用以下内容来正确命名:

  1. 创建一个直接链接,其中包含要显示在目标Detail-element中的所有元素。 Direct links to get the names right

  2. “验证图”以获取xslt。复制Detail-element及其内容。

  3. 删除所有到Detail元素的直接链接。

  4. 在源Container / Details / Detail和目标Detail之间添加一个循环的functoid。

  5. 添加脚本功能,将其连接到目标Detail。选择“内联XSLT”,然后粘贴您在步骤2中复制的代码。

  6. 测试地图,以验证其大部分功能是否正确(尽管“运货/详细信息/详细信息”仍然是错误的)

  7. 修改脚本功能中的xslt。您希望变量指向与当前行相对应的Shipment / Details / Detail元素。

根据当前LineId设置变量:

<xsl:variable name="CurrentShipmentDetail" select="../../../../Details/Detail[LineId=current()/LineId]"/>
  1. 修改元素,以便从变量中选择

之前:

<RequestedQty>
    <xsl:value-of select="../../../../Details/Detail/RequestedQty/text()" />
</RequestedQty> 

之后:

<RequestedQty>
    <xsl:value-of select="$CurrentShipmentDetail/RequestedQty/text()" />
</RequestedQty>

完整地图:

enter image description here

以及完整的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中构建循环和条件。您可以从那里进行调整。