首页 > 解决方案 > 如何使用 BizTalk 映射器通过将 2 个不同的重复节点连接到 1 个重复节点来进行映射

问题描述

问题是我需要遍历一个重复节点,但还要从基于 LineId 匹配的兄弟重复节点中提取信息。如果这是一个数据库,我会将每个重复节点等同于一个表,并希望根据匹配的 id 输出两个表的连接。

我首先将 Root/Shipments/Shipment/Containers/Container 循环到 Document/Header/Detail 并且这似乎有效,因为我想为来自源的每个 Container 创建 1 条记录作为目标中的 1 Detail 记录。但是当我从 Root/Shipments/Shipment/Details/Detail 映射字段时,我只从映射的第一条记录中获取数据,而不是从具有匹配 LineId 的记录中获取数据。然后我尝试将 Root/Shipments/Shipment/Details/Detail 添加到循环中,并有条件地抑制 LineId 在节点之间不匹配但不起作用的 Document/Detail。因此,我尝试在具有相同抑制条件的 Detail 上添加第二个循环,但这也不起作用。然后我想我会尝试使用 XSLT 模板来“查找”基于 LineId 作为输入的 Root/Shipments/Shipment/Details/Detail 中的数据,但它从未返回任何数据(它始终为空)。此外,要在字段级别分别获取每个字段,我需要搜索 X 次,我需要映射的每个字段 1 次,而不是每条记录 1 次,所以这似乎也效率低下。

我的 XSLT 知识有限。如果可能的话,我更愿意将 Mapping 与脚本 functoid 一起使用,而不是纯 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>

标签: joinmappingnodesbiztalkrepeat

解决方案


我不确定它是不是最好的解决方案,但我有一些东西可能会让你继续前进。这个想法是使用脚本函数在目标文档中创建 Detail 元素。

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

  1. 创建与您希望出现在目标详细信息元素中的所有元素的直接链接。 直接链接以获得正确的名称

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

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

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

  5. 添加一个脚本functoid,将它连接到目标Detail。选择 Inline XSLT 并粘贴您在步骤 2 中复制的代码。

  6. 测试地图,以验证它的大部分是否有效(尽管 Shipment/Details/Detail 仍然是错误的)

  7. 修改脚本functoid中的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>

完整地图:

在此处输入图像描述

以及完整的 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>

推荐阅读