如何在XSLT中基于属性值对元素进行分组?

时间:2014-11-26 07:24:48

标签: xml xslt xpath

XSLT新手。

这是XML。

<Resource resource_id="603">
    <Computer full_name="AJAY-2064" remarks="computer key expired."/>
</Resource>
<Resource resource_id="604">
    <Computer full_name="AJAY-2070" remarks="computer key expired."/>
</Resource>
<Resource resource_id="602">
    <Computer full_name="AJAY-1662" remarks="Not a valid key. "/>
</Resource>

我的要求是获取唯一的备注,并根据备注对名称进行分组。

(即)

计算机密钥已过期Count(2)

AJAY-2064
AJAY-2070

不是有效密钥(1)

AJAY-1662

这是xsl。

<xsl:variable name="license.computer" select="Resource/ManagedComputer"/>

<xsl:key name="keyComputer" match="$license.computer" use="@remarks"/>

<xsl:for-each select="$license.computer[generate-id() =
                    generate-id(key('keyComputer', @remarks)[1])]">
           <xsl:variable name="license.remarks" select="@remarks"/>

           <xsl:for-each select="$license.computer[contains(@remarks,$license.remarks)]">
                                      <xsl:choose>
                                          <xsl:when test="position() mod  2 = 0" >
                                            <tr>
                                                    <td bgcolor="#F9F9F9"><xsl:value-of select="@full_name"/></td>
                                                    <td bgcolor="#F9F9F9"><xsl:value-of select="@remarks"/></td>
                                            </tr>
                                          </xsl:when>
                                          <xsl:otherwise>
                                              <tr>
                                                    <td bgcolor="#FFFFFF"><xsl:value-of select="@full_name"/></td>
                                                    <td bgcolor="#FFFFFF"><xsl:value-of select="@remarks"/></td>
                                              </tr>
                                          </xsl:otherwise>
                                      </xsl:choose>

           </xsl:for-each>
</xsl:for-each>

但它似乎并没有起作用。如果有,请提供任何解决方法。任何调试xslt的调试器?

1 个答案:

答案 0 :(得分:1)

有很多原因导致它“无法正常工作”,尽管其中一些原因可能是由于问题没有完全代表您的实际代码。

但是,第一个问题是您的license.computer变量。假设这是一个全局变量,而不是匹配root的模板,xpath表达式将相对于文档节点,因此正在寻找Resource的根元素。但我猜你有一个不同的根元素,所以它可能需要看起来像这样....

<xsl:variable name="license.computer" select="//Resource/Computer"/>

(另请注意,您的XSLT引用ManagedComputer但您的XML示例仅显示Computer

接下来,是否允许您在键的匹配条件下使用变量,因此您的键实际上应该是这样的

<xsl:key name="keyComputer" match="//Resource/Computer" use="@remarks"/>

另外值得注意的是,虽然它在您的XSLT中实际上不是问题,但是要迭代组中的元素,您可以用此替换内部xsl:for-each

 <xsl:for-each select="key('keyComputer', @remarks)">

试试这个XSLT 实际上,您也可以像这样定义它,因为您不需要完整的xpath表达式,除非您想限制它匹配的Computer个元素

<xsl:key name="keyComputer" match="Computer" use="@remarks"/>

试试这个XSLT

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

   <xsl:variable name="license.computer" select="//Resource/Computer"/>
   <xsl:key name="keyComputer" match="Computer" use="@remarks"/>

   <xsl:template match="/">
      <xsl:for-each select="$license.computer[generate-id() = generate-id(key('keyComputer', @remarks)[1])]">      
          <xsl:for-each select="key('keyComputer', @remarks)">
              <xsl:variable name="bgcolor">
                 <xsl:choose>
                    <xsl:when test="position() mod  2 = 0" >#F9F9F9</xsl:when>
                    <xsl:otherwise>#FFFFFF</xsl:otherwise>
                </xsl:choose>
              </xsl:variable>
              <tr>
                  <td bgcolor="{$bgcolor}"><xsl:value-of select="@full_name"/></td>
                  <td bgcolor="{$bgcolor}"><xsl:value-of select="@remarks"/></td>
             </tr>
          </xsl:for-each>
      </xsl:for-each>
   </xsl:template>
</xsl:stylesheet>

另请注意,我已经重新设置了单元格的背景颜色,以避免重复代码。