Xml XSLT如何基于元素进行合并
我有以下输入XML:Xml XSLT如何基于元素进行合并,xml,xslt,xslt-1.0,Xml,Xslt,Xslt 1.0,我有以下输入XML: <Fees> <user> <value>userA</value> </user> <feeList> <userFee> <owner> <Id>owner1</Id> </owner> <Amount> <su
<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>
到目前为止,我有以下XSLT:(…我仍在与团队斗争并合并他们。)
用户:
计数:
总额:
所有者和金额:,
不幸的是,它仅限于XSLT1.0。
谢谢正如托马拉克所提到的,这是我们的一项任务。在这个标签下,你会发现很多关于如何使用它的例子。一开始使用它可能有点棘手,因为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>
</xsl:text>
</xsl:for-each>
Total count: <xsl:value-of select="count(feeList/userFee)" />
</xsl:template>
</xsl:stylesheet>
我是说,我想数到3。每个所有者的计数为1。还有,我 当我有多个
时,我遇到了问题。在
我只举了一个例子,但实际上可以有很多。
是每个用户一个,并且我在实际应用中有多个用户
文件我认为问题在于
查看整个文件。我可以吗
使此键只查看每个
元素
基于对另一个答案的评论,我觉得您需要使用一个复合键,同时使用owner/ID和user/value
如果你用一个包含多个用户
和相应的feeList
的示例更新了你的问题,那么就更容易确定了
另外,要获得每个用户的所有者数量,可以创建一个变量,为每个所有者输出一个字符串。字符串的长度将是所有者的数量。也许有更好的方法可以做到这一点,但现在还没有想到
完整示例
XML输入(更新为有多个用户
和feeList
)
Fiddle:您真的仅限于XSLT-1.0吗?或者您可以使用更高版本吗?@zx485不幸地限于XSLT-1.0这是一项基本的分组任务。上面有无数的答案,说明了如何在XSLT1.0中进行分组。搜索Muenchian分组,您将获得更多需要的示例。非常感谢@zx485。一个简单的问题,我如何得到这里的总计数?因为owner1重复了两次,所以我希望总计数为“3”,而不是4()。由于变量在xslt中是可变的,我不能在for循环中使用计数器,因为weelI在答案中添加了一个
Total count
输出。该值为4=2*owner1+1*owner2+1*owner3
。给定XML中只有两个owner1
条目。和:xsl:variable
s是不可变的-就像在许多其他函数式语言中一样。我的意思是,我希望计数为3。每个所有者的计数为1。此外,当我有多个问题时,我也遇到了问题。在这个例子中,我只给出了一个,但实际上可以有很多。是每个用户一个,实际文件中有多个用户。我认为问题在于查看整个文件。我能让这把钥匙看看每个元素吗?谢谢@zx485。我需要为每个用户按所有者/Id分组。所有者/ID可能会为其他用户重复,这很好,但是如果所有者为同一用户重复,那么只有我希望它被分组。非常感谢@Daniel Haley。正是我需要的。我更新了问题中的输入。
<?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>
<?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>
</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
<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>
<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>
</xsl:text></xsl:if>
<xsl:value-of select="concat('User: ',preceding-sibling::user[1]/value,'
')"/>
<xsl:value-of select="concat('Total Sum: ',sum(userFee/Amount/sum),'
')"/>
<xsl:value-of select="concat('Count: ', string-length($totalOwners), '
')"/>
<xsl:for-each
select="userFee[count(.|key('user_fees',concat(../preceding-sibling::user[1]/value,'~',owner/Id))[1])=1]">
<xsl:value-of
select="concat('	owner and amount: ',
owner/Id,
', ',
sum(key('user_fees',concat(../preceding-sibling::user[1]/value,'~',owner/Id))/Amount/sum),'
')"/>
</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