首页 > 解决方案 > 是否可以使用 XSLT 1.0 对条目进行分组?

问题描述

我正在研究一种使 XML 选择列表更易于阅读的方法。数据看起来像这样:

<data>
  <entry>
    <customer>Acme</customer>
    <sku>123123</sku>
    <desc>Name Of First Product</desc>
  </entry>
  <entry>
    <customer>GeneriCo</customer>
    <sku>456456</sku>
    <desc>Name Of Second Product</desc>
  </entry>
  <entry>
    <customer>Acme</customer>
    <sku>789789</sku>
    <desc>Name Of Third Product</desc>
  </entry>
</data>

我要做的是过滤数据,以便将每个客户订购的所有产品组合在一起(客户不一定需要排序)。像这样的东西:

Acme:
    123123 Name of First Product
    789789 Name of Third Product

GeneriCo:
    456456 Name of Second Product

我已经看过的问题:

由于我们工作环境的限制,升级到 XSLT 2.0 或 3.0 不是一种选择。如果在 XSLT 1.0 中无法解决这个问题,我将不得不完全抛开这整个思路,开始为 PHP 仪表板或其他东西进行宣传。

标签: xmlxsltxpathxslt-1.0

解决方案


不管这篇文章的评论如何,我们都可以使用另一个Muenchian 示例!,主要是因为分组发生的上下文不同,所以这是为OP量身定做的,根据这篇帖子:https ://stackoverflow.com/a/2334224/1690217

  1. 定义密钥解析器,在本例中customerentry

    <xsl:key name="customers" match="entry" use="customer" />
    
  2. 选择唯一的分组值

    <xsl:apply-templates select="data/entry[generate-id()=generate-id(key('customers',customer)[1])]"/>
    
  3. 为每个元素定义模板,在本例中为条目

     <xsl:template match="entry">
         <h1>
             <xsl:value-of select="customer"/>
         </h1>
         <table id="{customer}">
             <tr class="heading">
                 <th scope="col">SKU</th>
                 <th scope="col">Description</th>
             </tr>
             <xsl:for-each select="key('customers', customer)">
                 <tr>
                     <td>
                         <xsl:value-of select="sku"/>
                     </td>
                     <td>
                         <xsl:value-of select="desc"/>
                     </td>
                 </tr>
             </xsl:for-each>
         </table>
     </xsl:template>
    

在行动中看到它:http: //xsltransform.net/nc4P6y1/3

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

    <xsl:key name="customers" match="entry" use="customer" />
    
    <xsl:template match="entry">
        <h1>
            <xsl:value-of select="customer"/>
        </h1>
        <table id="{customer}">
            <tr class="heading">
                <th scope="col">SKU</th>
                <th scope="col">Description</th>
            </tr>
            <xsl:for-each select="key('customers', customer)">
                <tr>
                    <td>
                        <xsl:value-of select="sku"/>
                    </td>
                    <td>
                        <xsl:value-of select="desc"/>
                    </td>
                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>
    
    <xsl:template match="/">
      <html>
        <head>
          <title>Group By Customer</title>
        </head>
        <body>
            <xsl:apply-templates select="data/entry[generate-id()=generate-id(key('customers',customer)[1])]"/>
        </body>
      </html>
    </xsl:template>
    
</xsl:transform>

<!DOCTYPE html
  PUBLIC "XSLT-compat">
<html>
   <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Group By Customer</title>
   </head>
   <body>
  <h1>Acme</h1>
  <table id="Acme">
     <tr class="heading">
        <th scope="col">SKU</th>
        <th scope="col">Description</th>
     </tr>
     <tr>
        <td>123123</td>
        <td>Name Of First Product</td>
     </tr>
     <tr>
        <td>789789</td>
        <td>Name Of Third Product</td>
     </tr>
  </table>
  <h1>GeneriCo</h1>
  <table id="GeneriCo">
     <tr class="heading">
        <th scope="col">SKU</th>
        <th scope="col">Description</th>
     </tr>
     <tr>
        <td>456456</td>
        <td>Name Of Second Product</td>
     </tr>
  </table>
   </body>
</html>


推荐阅读