简体   繁体   English

如何基于两个不同的标签合并XML标签?

[英]How to merge xml tags based on two different tags?

In the below sample xml ASNOutDesc can have multiple ASNOutDistro's and each ASNOutDistro can have multiple ASNOutCtn's, under each ASNOutCtn there can be multiple ASNOutItem, All items under each ASNOutCtn must be merged and the unit_qty must be added. 在下面的示例xml中,ASNOutDesc可以具有多个ASNOutDistro,每个ASNOutDistro可以具有多个ASNOutCtn,在每个ASNOutCtn下可以有多个ASNOutItem,每个ASNOutCtn下的所有项都必须合并,并且必须添加unit_qty。 Iam trying with the below xslt, but it is merg 我尝试使用下面的xslt,但这是merg

Input XML: 输入XML:

<ASNoutDesc>
  <ASNOutDesc>
    <to_location>14</to_location>
    <from_location>777</from_location>
    <asn_nbr>Bol1</asn_nbr>
    <container_qty>3</container_qty>
    <shipment_date>2012-04-20T15:37:30.757</shipment_date>
    <ASNOutDistro>
      <distro_nbr>101</distro_nbr>
      <distro_doc_type>A</distro_doc_type>
      <ASNOutCtn>
        <container_id>1</container_id>
        <ASNOutItem>
          <item_id>item-1</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
        <ASNOutItem>
          <item_id>item-1</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
      </ASNOutCtn>
    </ASNOutDistro>
    <ASNOutDistro>
      <distro_nbr>102</distro_nbr>
      <distro_doc_type>A</distro_doc_type>
      <ASNOutCtn>
        <container_id>2</container_id>
        <ASNOutItem>
          <item_id>item-1</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
        <ASNOutItem>
          <item_id>item-2</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
        <ASNOutItem>
          <item_id>item-2</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
      </ASNOutCtn>
      <ASNOutCtn>
        <container_id>3</container_id>
        <ASNOutItem>
          <item_id>item-1</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
        <ASNOutItem>
          <item_id>item-2</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
      </ASNOutCtn>
    </ASNOutDistro>
  </ASNOutDesc>
</ASNoutDesc>

Required output: 要求的输出:

<ASNoutDesc>
  <ASNOutDesc>
    <to_location>14</to_location>
    <from_location>777</from_location>
    <asn_nbr>Bol1</asn_nbr>
    <container_qty>3</container_qty>
    <shipment_date>2012-04-20T15:37:30.757</shipment_date>
    <ASNOutDistro>
      <distro_nbr>101</distro_nbr>
      <distro_doc_type>A</distro_doc_type>
      <ASNOutCtn>
        <container_id>1</container_id>
        <ASNOutItem>
          <item_id>item-1</item_id>
          <unit_qty>4</unit_qty>
        </ASNOutItem>
      </ASNOutCtn>
    </ASNOutDistro>
    <ASNOutDistro>
      <distro_nbr>102</distro_nbr>
      <distro_doc_type>A</distro_doc_type>
      <ASNOutCtn>
        <container_id>2</container_id>
        <ASNOutItem>
          <item_id>item-1</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
        <ASNOutItem>
          <item_id>item-2</item_id>
          <unit_qty>4</unit_qty>
        </ASNOutItem>
      </ASNOutCtn>
      <ASNOutCtn>
        <container_id>3</container_id>
        <ASNOutItem>
          <item_id>item-1</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
        <ASNOutItem>
          <item_id>item-2</item_id>
          <unit_qty>2</unit_qty>
        </ASNOutItem>
      </ASNOutCtn>
    </ASNOutDistro>
  </ASNOutDesc>
</ASNoutDesc>

As shown above it has to merge the items in each ASNOutCtn under each ASNOutDistro. 如上所示,它必须在每个ASNOutDistro下合并每个ASNOutCtn中的项目。

XSLT Iam using: XSLT Iam使用:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:key name="kByI" match="ASNOutItem" use="item_id"/>
  <xsl:template match="node()|@*">
    <xsl:param name="pNewValueQty"/>
    <xsl:copy>
      <xsl:apply-templates select="node()|@*">
        <xsl:with-param name="pNewValueQty" select="$pNewValueQty"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="ASNOutItem[generate-id()=generate-id(key('kByI',item_id)[1])]">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*">
        <xsl:with-param name="pNewValueQty" select="sum(key('kByI',item_id)/unit_qty)"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="ASNOutItem"/>
  <xsl:template match="unit_qty/text()">
    <xsl:param name="pNewValueQty"/>
    <xsl:value-of select="$pNewValueQty"/>
  </xsl:template>
</xsl:stylesheet>

Output I got: 我得到的输出:

<ASNoutDesc>
  <ASNOutDesc>
    <to_location>14</to_location>
    <from_location>777</from_location>
    <asn_nbr>Bol1</asn_nbr>
    <container_qty>3</container_qty>
    <shipment_date>2012-04-20T15:37:30.757</shipment_date>
    <ASNOutDistro>
      <distro_nbr>101</distro_nbr>
      <distro_doc_type>A</distro_doc_type>
      <ASNOutCtn>
        <container_id>1</container_id>
        <ASNOutItem>
          <item_id>item-1</item_id>
          <unit_qty>8</unit_qty>
        </ASNOutItem>
      </ASNOutCtn>
    </ASNOutDistro>
    <ASNOutDistro>
      <distro_nbr>102</distro_nbr>
      <distro_doc_type>A</distro_doc_type>
      <ASNOutCtn>
        <container_id>2</container_id>
        <ASNOutItem>
          <item_id>item-2</item_id>
          <unit_qty>6</unit_qty>
        </ASNOutItem>
      </ASNOutCtn>
      <ASNOutCtn>
        <container_id>3</container_id>
      </ASNOutCtn>
    </ASNOutDistro>
  </ASNOutDesc>
</ASNoutDesc>

-My code is merging all items in the xml.Please help me in getting required output. -我的代码正在合并xml中的所有项目。请帮助我获取所需的输出。

Thanks in advance. 提前致谢。

Where you went wrong was to forget to factor in the parent nodes in the grouping of ASNOutItem nodes. 出错的地方是忘记将ASNOutItem节点分组中的父节点包括在内。 Your key definition should be keyed on a untion of item_id and the ASNOutCtn node which is the parent of ASNOutItem, as the grouping does not cross ASNOutCtn boundaries. 您的键定义应该在item_id和ASNOutCtn节点(它是ASNOutItem的父节点)的一个键上进行键控,因为分组不会跨越ASNOutCtn边界。

This style-sheet is what you want ... 这个样式表就是您想要的...

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="kByI" match="ASNOutItem" use="concat(item_id,'+',generate-id(parent::*))"/>

<xsl:template match="@*|node()">
 <xsl:copy>
  <xsl:apply-templates select="@*|node()"/>
 </xsl:copy>
</xsl:template>

<xsl:template match="ASNOutCtn">
 <xsl:copy>
  <xsl:apply-templates select="@*"/>
  <xsl:apply-templates select="node()[not(self::ASNOutItem)]"/>
  <xsl:apply-templates
    select="ASNOutItem[
     generate-id(.) =
     generate-id( key('kByI',concat(item_id,'+',generate-id(parent::*)))[1])]"
    mode="merge"/>
 </xsl:copy>
</xsl:template>

<xsl:template match="ASNOutItem" mode="merge">
 <xsl:copy>
  <xsl:apply-templates select="@*"/>
  <xsl:apply-templates select="node()[not(self::unit_qty)]"/>
  <unit_qty>
    <xsl:value-of select="sum(
      key('kByI',concat(item_id,'+',generate-id(parent::*)))/unit_qty)" />
  </unit_qty>
 </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Why not use a sum(ASNOutItem/item_id) ? 为什么不使用sum(ASNOutItem/item_id)呢?

Sorry if I ask, but in my opinion if I look at that code in a year it will take a tons of time to understand what I did and what it is doing. 抱歉,如果我询问,但是我认为如果我在一年后查看该代码,将需要大量的时间来了解我的工作和工作情况。 I would prefer to do something like: 我希望做类似的事情:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<ASNoutDesc>
    <ASNOutDesc>
        <xsl:copy-of select="*[name() != 'ASNOutDistro']"/>
        <xsl:for-each select="ASNOutDistro">
            <xsl:copy-of select="*[name() != 'ASNOutCtn']"/>
            <xsl:for-each select="ASNOutCtn">
                <ASNOutCtn>
                    <xsl:copy-of select="*[name() != 'ASNOutItem']"/>
                    <ASNOutItem>
                        <xsl:copy-of select="ASNOutItem[1]/*[name() != 'unit_qty']"/>
                        <unit_qty>
                            <xsl:value-of select="sum(ASNOutItem/*/unit_qty)"/>
                        </unit_qty>
                    </ASNOutItem>
                </ASNOutCtn>
            </xsl:for-each>
        </xsl:for-each>
    </ASNOutDesc>
</ASNoutDesc>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM