2012-07-13 53 views
0

在下面的示例XML ASNOutDesc可以有多个ASNOutDistro的每个ASNOutDistro可以有多个ASNOutCtn的,每个ASNOutCtn下可以有多个ASNOutItem,所有各ASNOutCtn下的项目必须合并,并必须加上unit_qty。 IAM与下面的XSLT努力,但MERG如何基于两个不同的标签合并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> 

需要的输出:

<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> 

如上所示,它合并在每个项目ASNOutDistro下的ASNOutCtn。

XSLT荫使用:

<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> 

输出我:

<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> 

- 我的代码合并在xml.Please所有项目帮助我获得所需的输出。

在此先感谢。

+0

是否有可能修改,以减少对XML膏的长度问题?请确保只发布足够的代码,以便我们了解您的需求/发生了什么问题。如果代码只是以不同的方式重复,但最终是类似结构的迭代,则可以省略这些代码。 – Utkanos 2012-07-13 13:46:37

回答

0

你在哪里错了就是忘了在ASNOutItem节点的分组父节点因素。您的密钥定义应该以item_id和ASNOutItem的父节点ASNOutCtn节点为关键字,因为该组不跨越ASNOutCtn边界。

这个样式表是你想要的...

<?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> 
+0

.Thank U Sooo多。 Iam对xslt甚至软件行业非常陌生。目前Iam正在开展一个整合项目,该项目的大部分都包括转换。你能帮我找到合适的材料,从基本的XML处理开始。谢谢:) – user1522626 2012-07-16 05:58:57

+0

http://stackoverflow.com/questions/4822075/best-book-to-learn-xslt – 2012-07-16 10:40:19

-1

为什么不使用sum(ASNOutItem/item_id)

对不起,如果我问,但在我看来,如果我看在一年的代码将花费大量的时间来了解我做了什么和它在做什么。我宁愿做这样的事情:

<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>