现在的位置: 首页 > 综合 > 正文

XSLT入门 — 第2章 基础篇: XSLT快速参考2 [转]

2014年02月08日 ⁄ 综合 ⁄ 共 6022字 ⁄ 字号 评论关闭
文章目录

6 循环

需要循环进行处理时可以使用xsl:for-each元素。基本代码如下所示。

<xsl:for-each
  select = "节点集合">
  <!-- 内容:(xsl:sort*, 模板) -->
</xsl:for-eaxh>

必须设置select属性,来指定被处理的节点集合。如果使用了后面讲述的排序的话则按照排序结果的顺序进行处理,否则按照节点出现顺序进行处理。

例如,如下所示,bookmark元素中包含了多个link元素。

<bookmark>
  <link>
    <title>技术评论公司</title>
    <url>http://www.gihyo.co.jp</url>
  </link>
  <link>
    <title>ONGS</title>
    <url>http://www.ongs.gr.jp</url>
  </link>
</bookmark>

利用下面使用了xsl:for-each元素的模板规则,可以将其转换成HTML表格(图1)。

<xsl:template match="bookmark">
  <table border="1"> 
    <xsl:for-each select="link">
      <tr> 
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="url"/></td>
      </tr>
    </xsl:for-each>
  </table>
</xsl:template>

图1: 使用表格进行显示

但是,使用如下所示的模板规则,不用xsl:for-each元素也能得到同样的输出结果。

<xsl:template match="bookmark">
  <table border="1"> 
    <xsl:apply-templates select="link"/>
  </table>
</xsl:template>
<xsl:template match="link">
   <tr>
     <td><xsl:value-of select="title"/></td>
     <td><xsl:value-of select="url"/></td>
   </tr>
</xsl:template>

仅定义模板规则有时候很难进行转换。例如,需要将行和列交换生成如图2所示的表时,不使用xsl:for-each元素就很难做到。

图2: 行列交换

使用xsl:for-each元素可以生成如图2所示的输出结果。

<xsl:template match="bookmark">
  <table border="1"> 
    <tr> 
      <xsl:for-each select="link/title">
        <td><xsl:value-of select="."/></td>
      </xsl:for-each>
    </tr>
    <tr> 
      <xsl:for-each select="link/url">
        <td><xsl:value-of select="."/></td>
      </xsl:for-each>
    </tr>
  </table>
</xsl:template>

7 条件处理

在XSLT中,进行条件处理的元素有xsl:if和xsl:choose两个。xsl:if进行“如果~就~”的if-then型处理,xsl:choose当有多个选择项存在时进行处理。

7.1 xsl:if

xsl:if元素拥有test属性,可指定逻辑表达式。逻辑表达式为真的情况下执行模板的转换,假的情况下不进行转换。

<xsl:if
  test = "逻辑表达式">
  <!-- 内容: 模板 -->
</xsl:if>

例如,对以下XML文档,

<people>
  <person>
    <name>张三</name>
    <age>30</age>
  </person>
  <person>
    <name>李四</name>
    <age>20</age>
  </person>
  <person>
    <name>周五</name>
    <age>10</age>
  </person>
</people>

使用如下所示的模板进行变换。

<xsl:template match="people">
  <ul>
    <xsl:apply-templates select="person"/>
  </ul>
</xsl:template>
<xsl:template match="person">
  <li>
    <xsl:value-of select="name"/>今年
    <xsl:value-of select="age"/>岁
    <xsl:if test="age[.&lt; 18]">
      (未成年)
    </xsl:if>
  </li>
</xsl:template>

&lt;是<的意思(&gt;是>)。age元素的值不足18的情况下输出“(未成年)”。输出结果如下所示。

<ul>
  <li>张三今年30岁</li>
  <li>李四今年20岁</li>
  <li>周五今年10岁(未成年)</li>
</ul>

7.2 xsl:choose

xsl:choose元素由一个或一个以上的xsl:when元素和可选的xsl:otherwise元素组成。

<xsl:choose>
  <xsl:when test="逻辑表达式">
    <!-- 内容: 模板 -->
  </xsl:when>
  <xsl:otherwise>
    <!-- 内容: 模板 -->
  </xsl:otherwise>
</xsl:choose>

与xsl:if元素相同,test属性的逻辑表达式为真的情况下执行指定的模板。从上到下依次测试xsl:when元素,但只有第一个逻辑表达式为真的xsl:when院所的模板会被执行。如果所有的xsl:when元素的逻辑表达式均为假,则执行xsl:otherwise元素所指定的模板。xsl:otherwise元素不存在时则不执行任何模板。

例如,对于如下文档,

<ol>
  <li>起床</li>
  <li>洗脸</li>
  <li>吃早饭</li>
  <li>上班</li>
</ol>

应用如下所示的模板。last()函数返回被处理的内容的大小。

  <xsl:template match="ol">
    <morning>
      <xsl:for-each select="li">
        <todo>
          <xsl:choose>
            <xsl:when test="position()=1">
              <xsl:text>首先</xsl:text>
            </xsl:when>
            <xsl:when test="position()=last()">
              <xsl:text>最后</xsl:text>
            </xsl:when>
            <xsl:otherwise>
              <xsl:text>第</xsl:text>
			   <xsl:value-of select="position()"/>
            </xsl:otherwise>
          </xsl:choose>
          <xsl:value-of select="."/>
        </todo>
      </xsl:for-each>
    </morning>
  </xsl:template>

输出结果如下所示。

  <morning>
    <todo>首先起床</todo>
    <todo>第2洗脸</todo>
    <todo>第3吃早饭</todo>
    <todo>最后上班</todo>
  </morning>

8 排序

为将数据排序,可以在xsl:apply-templates元素或xsl:for-each元素的子节点中增加xsl:sort元素。xsl:sort元素的基本代码如下所示。

<xsl:sort
  select = "字符串表达式"
  data-type = "数据类型"
  order = "顺序"/>

通过select属性指定排序的节点。通过data-type属性指定字符串的数据类型。设置为text就能够按照人们默认的字典顺序进行排序。设置为number将把字符串看作数字,按照数字的值进行排序。order属性设置排序的顺序。升序为ascending、降序为descending。未指定时默认为升序。其他能够设置的属性包括设置语言的lang属性,设置大小写字母哪个优先的case-order属性等。

例如,将如下所示的由姓名(name)、年龄(age)组成的人(person)的数据按照姓名和年龄进行排序。

<people>
  <person>
    <name>张三</name>
    <age>30</age>
  </person>
  <person>
    <name>李四</name>
    <age>20</age>
  </person>
  <person>
    <name>周五</name>
    <age>10</age>
  </person>
</people>

下面是按照年龄升序、姓名降序进行排序并生成HTML表格的模板规则。

<xsl:template match="people">
  <h1>按照年龄升序排列</h1>
  <table border="1">
    <xsl:apply-templates select="person">
      <xsl:sort select="age"
                data-type="number"/>
    </xsl:apply-templates>
  </table>
  <h1>按照姓名降序排列</h1>
  <table border="1">
    <xsl:apply-templates select="person">
      <xsl:sort select="name" data-type="text" order="descending"/>
    </xsl:apply-templates>
  </table>
</xsl:template>
<xsl:template match="person">
  <tr>
    <td><xsl:value-of select="name"/></td>
    <td><xsl:value-of select="age"/></td>
  </tr>
</xsl:template>

输出结果如图3所示。

图3: 排序结果

与此相同,使用xsl:for-each元素重新书写代码则如下所示。要注意,在将xsl:sort元素作为xsl:for-each元素的子节点使用时,必须将其写在开头的地方。

<xsl:template match="people">
  <h1>按照年龄降序排列</h1>
  <table border="1">
    <xsl:for-each select="person">
      <xsl:sort select="age" data-type="number"/>
      <tr>
        <td><xsl:value-of select="name"/></td>
        <td><xsl:value-of select="age"/></td>
      </tr>
    </xsl:for-each>
  </table>
  <h1>排序</h1>
  <table border="1">
    <xsl:for-each select="person">
      <xsl:sort select="name" data-type="text" order="descending"/>
      <tr>
        <td><xsl:value-of select="name"/></td>
        <td><xsl:value-of select="age"/></td>
      </tr>        
    </xsl:for-each>
  </table>
</xsl:template>

9 变量

在XSLT中可以使用变量。

9.1 绑定变量

可以为变量赋值的元素有xsl:variable元素和xsl:param元素。

9.1.1 xsl:variable元素

基本代码如下所示。

<xsl:variable
  name = "变量名"
  select = "表达式">
  <!-- 内容: 模板 -->
</xsl:variable>

使用name属性指定变量名(必须)。select属性和内容都不存在的话可以写成空字符串。

<xsl:variable name="x"/>

这种写法与下面的写法意思相同。

<xsl:variable name="x" select="''"/>

通过select属性可以指定变量中代入的值。使用select属性给变量赋值的话,内容必须为空。例如给变量x赋值为2时的代码如下所示。

<xsl:variable name="x" select="2"/>

这种情况下,使用

<xsl:value-of select="item[$x]"/>

将输出第二个item元素。

通过内容来赋值时,变量的值不是数值,而是结果树的片断。关于结果树的片断请参照参考文献[1]。

<xsl:variable name="x">2</xsl:variable>

这种情况下,使用

<xsl:value-of select="item[$x]"/>

不会输出第二个item元素,而是输出了第一个元素。使用值为结果树片断的变量时应当像下面这样书写代码。

<xsl:value-of select="item[position()=$x]"/>

9.1.2 xsl:param元素

xsl:variable元素和xsl:param元素基本上相同。一个区别是,XML解释器假定xsl:param变量中保存着默认值,并可以使用xsl:with-param元素来向模板中传值。详细情况请参见参考文献[1]。

9.2 访问变量

在表达式中访问变量时,需要在变量名前加上$符号。使用xsl:value-of元素访问变量则可以输出变量的值。

10 指定输出格式

XSLT处理器的任务是从XML文档转换成新的XML文档,但是也能够输出XML文档之外的格式。通过xsl:output元素可以指定输出格式。该元素只能作为顶层元素使用。基本代码如下所示。

<xsl:output 
  method = "输出格式"
  version = "版本" 
  encoding = "编码"
  omit-xml-declaration = "yes" | "no"
  standalone = "yes" | "no"
  indent = "yes" | "no" />

通过method指定输出格式。可以指定的格式包括html、html、text等。未指定时默认为xml,但如果满足以下条件则为html。

  • 结果树的根节点的元素名为html(不区分大小写),并且含有子元素。
  • 不包含命名空间的URI。
  • 结果树的根节点的子元素之前出现的文本只包含空白。

通过version可以指定输出格式的版本。通过encoding指定输出时使用的字符编码。通过omit-xml-declaration来指定是否省略XML定义。通过standalone指定是否输出独立文档的声明。通过indent指定输出结果树时是否使用缩进的格式。

例如,输出i-mode能够浏览的HTML时,可以如下书写代码。由于i-mode只能使用Shift_JIS编码,因此需要按下面的方式定义。

<xsl:output method="html" encoding="Shift_JIS" indent="no"/>


注释
1该表达式并不一定正确。详细情况请参见参考文献[5][6]。
2并不是所有的属性都能够使用属性值模板来处理。详细情况请参见参考文献[1]。
3实际上该例子作为动态生成的例子并不恰当。

抱歉!评论已关闭.