Miles' Blog

Welcome 2 My Planet

Available categories: [/] [development. ~]

xslt实现select distinct [Permalink]

Thu Nov 25 11:51:55 CST 2004

今天做显示支持的手机列表时候遇到一个技术问题,就是select distinct。目前状况是,一次选出所有的equipment纪录,每条记录带有自己的brand(品牌)信息。选出纪录可能是这样格式:

<ROW>
  <ID>1</ID>
  <BRAND>NOKIA</BRAND>
  <MODEL>6100</MODEL>
</ROW>
<ROW>
  <ID>2</ID>
  <BRAND>NOKIA</BRAND>
  <MODEL>7250</MODEL>
</ROW>
<ROW>
  <ID>3</ID>
  <BRAND>NOKIA</BRAND>
  <MODEL>8210</MODEL>
</ROW>
<ROW>
  <ID>4</ID>
  <BRAND>MOTO</BRAND>
  <MODEL>E365</MODEL>
</ROW>
<ROW>
  <ID>5</ID>
  <BRAND>NOKIA</BRAND>
  <MODEL>V3</MODEL>
</ROW>
...
这样的数据,我们需要组织成:
  1. 主card只显示brand,并提供连接到每个brand的model列表card;
  2. model列表card有多个,对应不同品牌。每个card显示所有该品牌的model。
问题很明白,就是需要用distinct来分类组织,让数据从2d变3d。用xslt/xpath2.0或者EXSL.NET十分方便,本身就有distinct功能;但是用xslt/xpath1.0就不那么容易了。下面就是最终使用的xsl文件:
<?xml version="1.0" encoding="gb2312"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="wml" omit-xml-declaration="no" indent="no" 
      doctype-public="-//WAPFORUM//DTD WML 1.1//EN" 
      doctype-system="http://www.wapforum.org/DTD/wml_1.1.xml" />

  <xsl:include href="../common/common.func.xsl"/>
  <xsl:include href="../common/header.inc.xsl"/>
  <xsl:include href="../common/footer.inc.xsl"/>

  <xsl:variable name="pn" select="/ROOT/EXTINFO/PAGENO"/>

  <xsl:template match="/">
    <wml>
      <card>
        <xsl:call-template name="inc.header"/>
        <p>
          <xsl:for-each select="/ROOT/DATA/ROW">
            <xsl:variable name="thisEm" select="EM_ID"/>

            <xsl:if test="count(preceding-sibling::ROW)=0">
              <a>
              <xsl:attribute name="href">#<xsl:value-of select="EM_ID"/></xsl:attribute>
                <xsl:value-of select="BRAND"/></a><br/>
            </xsl:if>

            <xsl:if test="preceding-sibling::ROW[1]/EM_ID != $thisEm">
              <a>
              <xsl:attribute name="href">#<xsl:value-of select="EM_ID"/></xsl:attribute>
              <xsl:value-of select="BRAND"/></a><br/>
            </xsl:if>
          </xsl:for-each>
        </p>
        <xsl:call-template name="inc.footer"/>
      </card>

      <xsl:for-each select="/ROOT/DATA/ROW">
        <xsl:variable name="thisEm" select="EM_ID"/>
        <xsl:if test="count(preceding-sibling::ROW)=0">
          <card>
          <xsl:attribute name="id"><xsl:value-of select="EM_ID"/></xsl:attribute>
            <xsl:call-template name="inc.header"/>
            <p align="center">品牌[<xsl:value-of select="BRAND"/>]的支持机型</p>
            <p>
              <xsl:for-each select="../ROW[EM_ID=$thisEm]">
               型号:<xsl:value-of select="MODEL"/><br/>
               描述:<xsl:value-of select="DESCRIPTION"/><br/>
              </xsl:for-each>
            </p>
            <xsl:call-template name="inc.footer"/>
          </card>
        </xsl:if>

        <xsl:if test="preceding-sibling::ROW[1]/EM_ID != $thisEm">
          <card>
            <xsl:attribute name="id"><xsl:value-of select="EM_ID"/></xsl:attribute>
            <xsl:call-template name="inc.header"/>
            <p align="center">品牌[<xsl:value-of select="BRAND"/>]的支持机型</p>
            <p>
              <xsl:for-each select="../ROW[EM_ID=$thisEm]">
               型号:<xsl:value-of select="MODEL"/><br/>
               描述:<xsl:value-of select="DESCRIPTION"/><br/>
              </xsl:for-each>
            </p>
            <xsl:call-template name="inc.footer"/>
          </card>
        </xsl:if>
      </xsl:for-each>
    </wml>
  </xsl:template>

</xsl:stylesheet>
绕着弯子实现简单功能,是xslt一大特点。 enjoy /images/emoticons/plain.gif

Posted by: miles

Comments on this entry





Author (*):
Verify Code (*):8 9 7 9
E-mail:
URL:
Comment (*):
Remember me?

Available categories: [/] [development. ~]

Powered By blojsom   RSS Feed  RSS2 Feed  RDF Feed