简体   繁体   English

使用XSLT计算唯一的XML元素属性

[英]Counting unique XML element attributes using XSLT

I've just started using XSLT and am trying to figure this out. 我刚刚开始使用XSLT,正在尝试解决这个问题。 Your help would be greatly appreciated. 您的帮助将不胜感激。

Example XML file 示例XML文件

<purchases>
    <item id = "1" customer_id = "5">
    </item>
    <item id = "2" customer_id = "5">
    </item>
    <item id = "7" customer_id = "4">
    </item>
</purchases>

Desired HTML Output: 所需的HTML输出:

<table>
    <tr><th>Customer ID</th><th>Number of Items Purchased</th></tr>
    <tr><td>5</td><td>2</td></tr>
    <tr><td>4</td><td>1</td></tr>
</table>

Customer with id number 5 has bought 2 items. 编号为5的客户购买了2件商品。 Customer with id number 4 has bought 1 item. 编号为4的客户购买了1件商品。

XSLT 1.0 solution .... XSLT 1.0解决方案....

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

      <xsl:template match="/">
        <table>
          <xsl:apply-templates select="purchases/item"/>     
        </table>
      </xsl:template>

   <xsl:template match="item">
     <xsl:if test="not(
       preceding-sibling::*[@customer_id=current()/@customer_id]
       )">     
         <tr><td><xsl:value-of select="@customer_id"/></td>
           <td><xsl:value-of select="count(following-sibling::item
             [@customer_id=current()/@customer_id])+1"/></td>
         </tr> 
     </xsl:if>   
  </xsl:template>

</xsl:stylesheet>

If you want XSLT 2.0 then the following XSLT should do the trick: 如果要使用XSLT 2.0,则以下XSLT应该可以解决问题:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output indent="yes"/>
    <xsl:template match="/purchases">
        <table>
            <tr>
                <th>Customer ID</th>
                <th>Number of Items Purchased</th>
            </tr>
            <xsl:for-each-group select="item" group-by="@customer_id">
                <tr>
                    <td>
                        <xsl:value-of select="current-grouping-key()"/>
                    </td>
                    <td>
                        <xsl:value-of select="count(current-group())"/>
                    </td>
                </tr>
            </xsl:for-each-group>
        </table>
    </xsl:template>
</xsl:stylesheet>

A possible Xslt 1.0 solution would be 可能的Xslt 1.0解决方案是

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes"/>

    <xsl:key name="kCustomer" match="item" use="@customer_id"/>

    <xsl:template match="/">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="purchases">
        <xsl:element name="table">
            <xsl:element name="tr">
                <xsl:element name="th">Customer ID</xsl:element>
                <xsl:element name="th">Number of Items Purchased</xsl:element>
                <xsl:for-each select="item[generate-id(.) = generate-id(key('kCustomer', @customer_id))]">
                    <xsl:variable name="total" select="count(/purchases/item[@customer_id=current()/@customer_id]/@id)" />
                    <xsl:element name="tr">
                        <xsl:element name="td">
                            <xsl:value-of select="./@customer_id" />
                        </xsl:element>
                        <xsl:element name="td">
                            <xsl:value-of select="$total" />
                        </xsl:element>
                    </xsl:element>
                </xsl:for-each>
            </xsl:element>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Adopted from Dimitres answer on How can I Group and sort based on sum . 来自Dimitres的答案如何根据和进行分组和排序


As pointed out by Dimitre the purchases template can be simplified to 正如Dimitre所指出的, 购买模板可以简化为

    <xsl:template match="purchases">
        <table>
            <tr>
                <th>Customer ID</th>
                <th>Number of Items Purchased</th>
            </tr>
            <xsl:for-each select="item[generate-id(.) = generate-id(key('kCustomer', @customer_id))]">
                <xsl:variable name="total" select="count(/purchases/item[@customer_id=current()/@customer_id]/@id)" />
                    <tr>
                        <td>
                            <xsl:value-of select="./@customer_id" />
                        </td>
                        <td>
                            <xsl:value-of select="$total" />
                        </td>
                    </tr>
            </xsl:for-each>
        </table>
    </xsl:template>

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

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