XSLT 如何基于元素进行合并



>我有以下输入XML:

<Fees>
<user>
    <value>userA</value>
</user>
<feeList>
    <userFee>
        <owner>
            <Id>owner1</Id>
        </owner>
        <Amount>
            <sum>100</sum>
        </Amount>
    </userFee>
    <userFee>
        <owner>
            <Id>owner1</Id>
        </owner>
        <Amount>
            <sum>100</sum>
        </Amount>
    </userFee>
    <userFee>
        <owner>
            <Id>owner2</Id>
        </owner>
        <Amount>
            <sum>100</sum>
        </Amount>
    </userFee>
    <userFee>
        <owner>
            <Id>owner3</Id>
        </owner>
        <Amount>
            <sum>100</sum>
        </Amount>
    </userFee>
</feeList>
<user>
    <value>userB</value>
</user>    
<feeList>
    <userFee>
        <owner>
            <Id>owner1</Id>
        </owner>
        <Amount>
            <sum>120</sum>
        </Amount>
    </userFee>
    <userFee>
        <owner>
            <Id>owner2</Id>
        </owner>
        <Amount>
            <sum>100</sum>
        </Amount>
    </userFee>
    <userFee>
        <owner>
            <Id>owner3</Id>
        </owner>
        <Amount>
            <sum>180</sum>
        </Amount>
    </userFee>
    <userFee>
        <owner>
            <Id>owner3</Id>
        </owner>
        <Amount>
            <sum>100</sum>
        </Amount>
    </userFee>
    <userFee>
        <owner>
            <Id>owner4</Id>
        </owner>
        <Amount>
            <sum>75</sum>
        </Amount>
    </userFee>
    <userFee>
        <owner>
            <Id>owner4</Id>
        </owner>
        <Amount>
            <sum>25</sum>
        </Amount>
    </userFee>
</feeList>

feeList中有 4 个userFee元素。其中两个属于同一个所有者"owner1",它们需要合并,因为其中 1 个和 2 个属于不同的所有者。我需要以下输出:

user: userA    
Total sum: 400
count: 3 (basically no. of unique owner id's for the user fee
    owner and amount: owner1, 200 (Note there are 2 owner1 elements, and they need to be merged into one row with their sum)   
    owner and amount: owner2, 100
    owner and amount: owner3, 100

到目前为止,我有以下 XSLT:
(...我仍在为组和合并它们而苦苦挣扎。

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="no" omit-xml-declaration="yes" />
  <xsl:template match="/">
    <xsl:for-each select="Fees">
   user: <xsl:value-of select="user/value"/>
      <!-- how to get count of unique userFee by owner ID -->
   Count:<xsl:value-of select="count(feeList/userFee)"/>
   Total Sum:<xsl:value-of select="sum(feeList/userFee/amount/sum)"/>
      <xsl:for-each select="feeList/userFee">
         <!-- how to group same owner into one and sum there amount -->
     owner and amount: <xsl:value-of select="owner/Id"/>, <xsl:value-of select="amount/sum"/>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

不幸的是,仅限于 XSLT 1.0。 谢谢

我的意思是,我希望计数是 3。每个所有者计数 1。另外,我 当我有多个<feeList>时遇到问题.在 例子我只举了一个,但实际上可以有很多。 <feeList>是每个用户一个,我实际上有多个用户 文件。我认为问题在于<xsl:key name="overall" match="userFee" use="owner/Id" />查看整个文件。我可以吗 让这个键只看每个<feeList>元素?

基于对另一个答案的评论,在我看来,您需要同时使用所有者/ID 和用户/值的组合键。

如果您使用包含多个user和相应feeList的示例更新了问题,则更容易确定。

此外,要获取每个用户的所有者数量,您可以创建一个变量,为每个所有者输出字符串字符。字符串的长度将是所有者的数量。可能有一个更好的方法可以做到这一点,但现在还没有想到。

完整示例...

XML 输入(更新为具有多个userfeeList(

<Fees>
    <user>
        <value>userA</value>
    </user>
    <feeList>
        <userFee>
            <owner>
                <Id>owner1</Id>
            </owner>
            <Amount>
                <sum>100</sum>
            </Amount>
        </userFee>
        <userFee>
            <owner>
                <Id>owner1</Id>
            </owner>
            <Amount>
                <sum>100</sum>
            </Amount>
        </userFee>
        <userFee>
            <owner>
                <Id>owner2</Id>
            </owner>
            <Amount>
                <sum>100</sum>
            </Amount>
        </userFee>
        <userFee>
            <owner>
                <Id>owner3</Id>
            </owner>
            <Amount>
                <sum>100</sum>
            </Amount>
        </userFee>
    </feeList>
    <user>
        <value>userB</value>
    </user>    
    <feeList>
        <userFee>
            <owner>
                <Id>owner1</Id>
            </owner>
            <Amount>
                <sum>120</sum>
            </Amount>
        </userFee>
        <userFee>
            <owner>
                <Id>owner2</Id>
            </owner>
            <Amount>
                <sum>100</sum>
            </Amount>
        </userFee>
        <userFee>
            <owner>
                <Id>owner3</Id>
            </owner>
            <Amount>
                <sum>180</sum>
            </Amount>
        </userFee>
        <userFee>
            <owner>
                <Id>owner3</Id>
            </owner>
            <Amount>
                <sum>100</sum>
            </Amount>
        </userFee>
        <userFee>
            <owner>
                <Id>owner4</Id>
            </owner>
            <Amount>
                <sum>75</sum>
            </Amount>
        </userFee>
        <userFee>
            <owner>
                <Id>owner4</Id>
            </owner>
            <Amount>
                <sum>25</sum>
            </Amount>
        </userFee>
    </feeList>
</Fees>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>
  <xsl:key name="user_fees" match="userFee" use="concat(../preceding-sibling::user[1]/value,'~',owner/Id)"/>
  <xsl:template match="/*">
    <xsl:for-each select="feeList">
      <xsl:variable name="totalOwners">
        <xsl:for-each select="userFee[count(.|key('user_fees',concat(../preceding-sibling::user[1]/value,'~',owner/Id))[1])=1]">
          <xsl:text>#</xsl:text>
        </xsl:for-each>
      </xsl:variable>
      <xsl:if test="position() > 1"><xsl:text>&#xA;</xsl:text></xsl:if>
      <xsl:value-of select="concat('User: ',preceding-sibling::user[1]/value,'&#xA;')"/>
      <xsl:value-of select="concat('Total Sum: ',sum(userFee/Amount/sum),'&#xA;')"/>
      <xsl:value-of select="concat('Count: ', string-length($totalOwners), '&#xA;')"/>
      <xsl:for-each 
        select="userFee[count(.|key('user_fees',concat(../preceding-sibling::user[1]/value,'~',owner/Id))[1])=1]">
        <xsl:value-of 
          select="concat('&#x9;owner and amount: ',
          owner/Id,
          ', ',
          sum(key('user_fees',concat(../preceding-sibling::user[1]/value,'~',owner/Id))/Amount/sum),'&#xA;')"/>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

输出

User: userA
Total Sum: 400
Count: 3
    owner and amount: owner1, 200
    owner and amount: owner2, 100
    owner and amount: owner3, 100
User: userB
Total Sum: 600
Count: 4
    owner and amount: owner1, 120
    owner and amount: owner2, 100
    owner and amount: owner3, 280
    owner and amount: owner4, 100

小提琴:http://xsltfiddle.liberty-development.net/nc4NzQ8

正如托马拉克所提到的,这是Muenchian Grouping的任务。在此标签下,您会发现很多如何使用它的示例。一开始使用起来可能有点棘手,因此 XSLT-2.0 为此类任务引入了更简单xsl:for-each-group

但是,这是应用此方法的一种解决方案:

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" omit-xml-declaration="yes" />
  <xsl:key name="overall" match="userFee" use="owner/Id" />   <!-- key required for Muenchian method -->
  <xsl:template match="/Fees">
    User: <xsl:value-of select="user/value"/>
    <!-- iterate over unique owners - Muenchian method -->
    <xsl:for-each select="feeList/userFee[generate-id() = generate-id(key('overall',owner/Id)[1])]">
      Owner:<xsl:value-of select="owner/Id"/>
      <!-- how to get count of unique userFee by owner ID -->
      Count:<xsl:value-of select="count(key('overall',owner/Id))"/>
      <!-- how to sum the amount of one owner -->
      Total Sum:<xsl:value-of select="sum(key('overall',owner/Id)/Amount/sum)"/>
      <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>
    Total count: <xsl:value-of select="count(feeList/userFee)" />
  </xsl:template>
</xsl:stylesheet>

输出为:

User: userA
Owner:owner1
Count:2
Total Sum:200
Owner:owner2
Count:1
Total Sum:100
Owner:owner3
Count:1
Total Sum:100
Total count: 4

相关内容

  • 没有找到相关文章

最新更新