基于两个不同的复杂标签合并标签



在下面的两个ASNInPO中,po_nbr相同container_id ASNInCtn下相同,ASNInItem 下的item_id是不同的。在这种情况下,必须合并两个 ASNInPO,并且必须将两个 ASNInCtn 合并到一个标签中。这是我的输入:

     <?xml version = '1.0' encoding = 'UTF-8'?>
 <ASNInDesc>
    <asn_nbr>ASN-1</asn_nbr>
    <ASNInPO>
      <po_nbr>PO-2</po_nbr>
      <ASNInCtn>
         <container_id>CONTAINER-2</container_id>
         <ASNInItem>
            <item_id>ITEM-2</item_id>
            <unit_qty>3</unit_qty>
         </ASNInItem>
      </ASNInCtn>
   </ASNInPO>
   <ASNInPO>
      <po_nbr>PO-2</po_nbr>
      <ASNInCtn>
         <container_id>CONTAINER-2</container_id>
         <ASNInItem>
            <item_id>ITEM-3</item_id>
            <unit_qty>3</unit_qty>
         </ASNInItem>
      </ASNInCtn>
   </ASNInPO>
  </ASNInDesc>

这是所需的输出:

<?xml version = '1.0' encoding = 'UTF-8'?>
 <ASNInDesc>
    <asn_nbr>ASN-1</asn_nbr>
    <ASNInPO>
      <po_nbr>PO-2</po_nbr>
      <ASNInCtn>
         <container_id>CONTAINER-2</container_id>
         <ASNInItem>
            <item_id>ITEM-2</item_id>
            <unit_qty>3</unit_qty>
         </ASNInItem>
         <ASNInItem>
            <item_id>ITEM-3</item_id>
            <unit_qty>3</unit_qty>
         </ASNInItem>        
      </ASNInCtn>
   </ASNInPO>
 </ASNInDesc>

请帮助我解决这个问题。

由于这个问题被标记为 xslt-1.0 ,我将发布一个 XSLT1.0 使用明基分组方法的解决方案。(也许有人else 将贡献一个 XSLT 2.0 解决方案。它可能是有启发性的比较它们。

让我们浏览一下样式表。

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

分组 1:按po_nbr ASNInPO元素

既然我们想按元素po_nbr对元素进行分组ASNInPO,让我们首先定义一个允许检索ASNInPO的键元素的po_nbr值。

  <xsl:key name="ASNInPO-by-po_nbr" 
           match="ASNInPO" use="po_nbr"/>

然后我们将编写一个与ASNInDesc匹配的模板。我们将制作一个元素的副本及其asn_nbr .现在我们要分组所包含的ASNInPO元素按其po_nbr.我们通过以下方式做到这一点将模板应用于每个组中的第一个ASNInPo

  <xsl:template match="ASNInDesc">
    <xsl:copy>
      <xsl:copy-of select="asn_nbr"/>
      <xsl:apply-templates select="ASNInPO[generate-id() =
                                   generate-id(key('ASNInPO-by-po_nbr', 
                                                   po_nbr)[1])]"/>
    </xsl:copy>
  </xsl:template>

分组 2:按container_id ASNInCtn元素

但在进一步讨论之前,我们需要定义另一个键。似乎就像我们需要按元素container_id对元素进行分组ASNInCtn(如果不是这种情况,请参阅下面的注释(。

  <xsl:key name="ASNInCtn-by-container_id" 
           match="ASNInCtn" use="container_id"/>

我们将在以下模板中需要与ASNInPO匹配的密钥元素。请记住,我们在这里处理的元素将是第一个他们小组中的一个,因为我们只选择了那些 xsl:apply-template上文。

这个模板类似于我们上面写的模板。我们制作副本元素本身及其po_nbr,然后再次应用模板到按其分组的前ASNInCtn元素 container_id

  <xsl:template match="ASNInPO">
    <xsl:copy>
      <xsl:copy-of select="po_nbr"/>
      <xsl:apply-templates select="key('ASNInPO-by-po_nbr', po_nbr)/
                                   ASNInCtn[generate-id() =
                                   generate-id(key('ASNInCtn-by-container_id',
                                                   container_id)[1])]"/>
    </xsl:copy>
  </xsl:template>

最后,我们编写与ASNInCtn元素匹配的模板。这复制元素本身及其container_id,然后复制所有 ASNInItem同一组中的元素:

  <xsl:template match="ASNInCtn">
    <xsl:copy>
      <xsl:copy-of select="container_id"/>
      <xsl:copy-of select="key('ASNInCtn-by-container_id', 
                               container_id)/ASNInItem"/>
    </xsl:copy>
  </xsl:template>

我们完成了。

</xsl:stylesheet>

注意

该解决方案假定ASNInCtn元素具有给定的 container_id只能出现在具有相同ASNInPO元素中 po_nbr .如果不是这种情况,则需要调整键 ASNInPO对象以使用 po_nbrcontainer_id 的组合。

最新更新