学习笔记——XSLT2.0实用的新功能

原创 2012年03月29日 17:39:35

2007年1月,W3C发布了XSLT2.0规范,2009年发布了XSLT2.1,XSLT3.0预计今年发布得意

 

分组

函数:node-set current-group():该函数返回分组所包含的节点集。

函数:node-set current-grouping-key():该函数返回当前分组的条件(控制分分组的关键节点)。

 

<!-- Category: instruction -->
<xsl:for-each-group
  select
= expression
  group-by? = expression
  group-adjacent? = expression
  group-starting-with? = pattern
  group-ending-with? = pattern
  collation? = { uri }>
  <!-- Content: (xsl:sort*, sequence-constructor) -->
</xsl:for-each-group>

 

属性详解:

1:select:用于指定需要分组的节点;

2:group-by:用于控制分组的关键节点;

3:group-adjacent:用于控制分组的关键节点,并且只将相邻的元素分为一组;

4:group-starting-with:指定分组的开始节点;

5:group-ending-with:指定分组的结束节点;

 

Example: Grouping Nodes based on Common Values

The following example groups a list of nodes based on common values. The resulting groups are numbered but unsorted, and a total is calculated for each group.

Source XML document:

<cities>
  <city name="Milano"  country="Italia"      pop="5"/>
  <city name="Paris"   country="France"      pop="7"/>
  <city name="München" country="Deutschland" pop="4"/>
  <city name="Lyon"    country="France"      pop="2"/>
  <city name="Venezia" country="Italia"      pop="1"/>
</cities>

 

Desired output:

<table>
  <tr>
    <th>Position</th>
    <th>Country</th>
    <th>List of Cities</th>
    <th>Population</th>
  </tr>
  <tr>
    <td>1</td>
    <td>Italia</td>
    <td>Milano, Venezia</td>
    <td>6</td>
  </tr>
  <tr>
    <td>2</td>
    <td>France</td>
    <td>Lyon, Paris</td>
    <td>9</td>
  </tr>  
  <tr>
    <td>3</td>
    <td>Deutschland</td>
    <td>München</td>
    <td>4</td>
  </tr>  
</table>

 

Solution:

<table xsl:version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <tr>
    <th>Position</th>
    <th>Country</th>
    <th>City List</th>
    <th>Population</th>
  </tr>
  <xsl:for-each-group select="cities/city" group-by="@country">
    <tr>
      <td><xsl:value-of select="position()"/></td>
      <td><xsl:value-of select="@country"/></td>
      <td>
        <xsl:value-of select="current-group()/@name" separator=", "/>
      </td>
      <td><xsl:value-of select="sum(current-group()/@pop)"/></td>
    </tr>
  </xsl:for-each-group>
</table>

 

自定义函数

<!-- Category: declaration -->
<xsl:function
  name = qname
  as? = sequence-type
  override? = "yes" | "no">
  <!-- Content: (xsl:param*, sequence-constructor) -->
</xsl:function>

 

属性详解:

1:name:函数名;

2:as:函数的返回值;

3:override:当存在同名函数时,是否覆盖。

 

<funciton.../>中可包含N个<param.../>子元素,用于为该函数定义形参。

 

<!-- Category: declaration -->
<xsl:param
  name = qname
  select? = expression
  as? = sequence-type
  required? = "yes" | "no"
  tunnel? = "yes" | "no">
  <!-- Content: sequence-constructor -->
</xsl:param>

 

属性详解:

as:指定形参的数据类型;

tunnel:默认是no,用于指定该参数是一个tunnel参数。

 

Example: A Stylesheet Function

The following example creates a recursive stylesheet function named str:reverse that reverses the words in a supplied sentence, and then invokes this function from within a template rule.

<xsl:transform 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:str="http://example.com/namespace"
  version="2.0"
  exclude-result-prefixes="str">

<xsl:function name="str:reverse" as="xs:string">
  <xsl:param name="sentence" as="xs:string"/>
  <xsl:sequence  
     select="if (contains($sentence, ' '))
             then concat(str:reverse(substring-after($sentence, ' ')),
                         ' ',
                         substring-before($sentence, ' '))
             else $sentence"/>
</xsl:function>

<xsl:template match="/">
<output>
  <xsl:value-of select="str:reverse('DOG BITES MAN')"/>
</output>
</xsl:template>

</xsl:transform>

 

An alternative way of writing the same function is to implement the conditional logic at the XSLT level, thus:

<xsl:function name="str:reverse" as="xs:string">
  <xsl:param name="sentence" as="xs:string"/>
  <xsl:choose>
    <xsl:when test="contains($sentence, ' ')">  
      <xsl:sequence select="concat(str:reverse(substring-after($sentence, ' ')),
                                ' ',
                                substring-before($sentence, ' '))"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:sequence select="$sentence"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function> 

 

Final Result Trees

<!-- Category: instruction -->
<xsl:result-document
  format? = { qname }
  href? = { uri-reference }
  validation? = "strict" | "lax" | "preserve" | "strip"
  type? = qname
  method? = { "xml" | "html" | "xhtml" | "text" | qname-but-not-ncname }
  byte-order-mark? = { "yes" | "no" }
  cdata-section-elements? = { qnames }
  doctype-public? = { string }
  doctype-system? = { string }
  encoding? = { string }
  escape-uri-attributes? = { "yes" | "no" }
  include-content-type? = { "yes" | "no" }
  indent? = { "yes" | "no" }
  media-type? = { string }
  normalization-form? = { "NFC" | "NFD" | "NFKC" | "NFKD" | "fully-normalized" | "none" |nmtoken }
  omit-xml-declaration? = { "yes" | "no" }
  standalone? = { "yes" | "no" | "omit" }
  undeclare-prefixes? = { "yes" | "no" }
  use-character-maps? = qnames
  output-version? = { nmtoken }>
  <!-- Content: sequence-constructor -->
</xsl:result-document>

 

属性解释:

1:format:指定输出结果文档的格式,属性值是一个<output.../>元素的name属性值。

2:href:指定输出结果文档的文件路径。

 

Example: Multiple Result Documents

The following example takes an XHTML document as input, and breaks it up so that the text following each <h1> element is included in a separate document. A new documenttoc.html is constructed to act as an index:

<xsl:stylesheet
        version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xhtml="http://www.w3.org/1999/xhtml">
        
<xsl:output name="toc-format" method="xhtml" indent="yes"
            doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
            doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"/>
            
<xsl:output name="section-format" method="xhtml" indent="no"
            doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
            doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>        
         
<xsl:template match="/">
  <xsl:result-document href="toc.html" format="toc-format" validation="strict">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head><title>Table of Contents</title></head>
      <body>
        <h1>Table of Contents</h1>
        <xsl:for-each select="/*/xhtml:body/(*[1] | xhtml:h1)">
          <p><a href="section{position()}.html"><xsl:value-of select="."/></a></p>
        </xsl:for-each>
      </body>
    </html>
  </xsl:result-document>
  <xsl:for-each-group select="/*/xhtml:body/*" group-starting-with="xhtml:h1">
    <xsl:result-document href="section{position()}.html" 
                         format="section-format" validation="strip">         
      <html xmlns="http://www.w3.org/1999/xhtml">
        <head><title><xsl:value-of select="."/></title></head>
        <body>
          <xsl:copy-of select="current-group()"/>
        </body>
      </html>
    </xsl:result-document>
  </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet> 

 

字符映射

<!-- Category: declaration -->
<xsl:character-map
  name = qname
  use-character-maps? = qnames>
  <!-- Content: (xsl:output-character*) -->
</xsl:character-map>

 

属性解释:

1:name:标识符;

2:use-character-maps:用于包含另外一个字符映射。

<xsl:output-character
  character = char
  string = string />

 

属性解释:

用character的属性值替代string的属性值。

 

Example: Using Character Maps to Generate Non-XML Output

Character maps can be useful when producing serialized output in a format that resembles, but is not strictly conformant to, HTML or XML. For example, when the output is a JSP page, there might be a need to generate the output:

<jsp:setProperty name="user" property="id" value='<%= "id" + idValue %>'/>


Although this output is not well-formed XML or HTML, it is valid in Java Server Pages. This can be achieved by allocating three Unicode characters (which are not needed for any other purpose) to represent the strings<%,%>, and ", for example:

<xsl:character-map name="jsp">
  <xsl:output-character character="«" string="<%"/>   
  <xsl:output-character character="»" string="%>"/>
  <xsl:output-character character="§" string='"'/>
</xsl:character-map>


When this character map is referenced in the xsl:output declaration, the required output can be produced by writing the following in the stylesheet:

<jsp:setProperty name="user" property="id" value='«= §id§ + idValue »'/>

 

This works on the assumption that when an apostrophe or quotation mark is generated as part of an attribute value by the use of character maps, the serializer will (where possible) use the other choice of delimiter around the attribute value.

 

数据类型绑定

在<variable.../>、<param.../>和<with-param.../>元素中使用as属性,指定其数据类型,前面示例中用过。

 

正则表达式

 

<!-- Category: instruction -->
<xsl:analyze-string
  select = expression
  regex = { string }
  flags? = { string }>
  <!-- Content: (xsl:matching-substring?, xsl:non-matching-substring?, xsl:fallback*) -->
</xsl:analyze-string>

<xsl:matching-substring>
  <!-- Content: sequence-constructor -->
</xsl:matching-substring>

<xsl:non-matching-substring>
  <!-- Content: sequence-constructor -->
</xsl:non-matching-substring>

 

呃!直接理解字面意思就可得意

 

Example: Parsing a Date

Problem: the input string contains a date such as 23 March 2002. Convert it to the form2002-03-23.

Solution (with no error handling if the input format is incorrect):

<xsl:variable name="months" select="'January', 'February', 'March', ..."/>

<xsl:analyze-string select="normalize-space($input)" 
    regex="([0-9]{{1,2}})\s([A-Z][a-z]+)\s([0-9]{{4}})">
    <xsl:matching-substring>
        <xsl:number value="regex-group(3)" format="0001"/>          
        <xsl:text>-</xsl:text>
        <xsl:number value="index-of($months, regex-group(2))" format="01"/>
        <xsl:text>-</xsl:text>
        <xsl:number value="regex-group(1)" format="01"/>
    </xsl:matching-substring>
</xsl:analyze-string>

 

Note the use of normalize-space to simplify the work done by the regular expression, and the use of doubled curly brackets because theregex attribute is an attribute value template.

 

XSLT(10) Sequence

Type Sequences have types, types can have occurrence indicators + * ? example: xs:dateTime+ elem...

XSLT2.0 xsl:for-each-group用法详解.

for-each-group是在XSLT2.0中增加进来的一个标签.其主要作用是对结果进行分组. 由此增加了current-group()和current-grouping-key()两个内置函数....

XSL自定义函数

利用微软的XSL的继承特性,用户可以自定义XSL函数.基本原理是用户写的脚本代码写在msxsl中,并设置这部分msxsl继承到用户自定义空间中,那么用户就可以通过用户自定义空间使用msxsl中的脚本代...
  • smalle
  • smalle
  • 2004年12月02日 13:53
  • 1176

基于XML-XSL的订单存储与拆分. xsl:function与xsl:result-document XSLT2.0

XSLT2.0新增了许多XSLT1.0不支持的功能. xsl:function与xsl:result-document属于其新增功能. xsl:function主要是通过将自定义方法关联到...

准备从 XSLT 1.0 升级到 2.0系列

 XSLT 2.0 引入了许多新特性,部分是为了克服 XSLT 1.0 的不足而专门设计的。本系列探讨了其中一些最值得期待的特性,并对如何从 XSLT 1.0 升级到 2.0 给出了五种策略,以及如何...

学习笔记——XSLT创建结果集

XSLT提供了一些元素用于直接创建元素、属性、文本、处理命令和注释等元素。   创建元素   name = { qname }   namespace = { uri-referenc...

XSLT轻松入门第五章:XSLT运算符

XSL中的运算符 表一、运算符与特殊字符  运算符 描述 / 选择子元素,返回左侧元素的直接子元素;如果"/"位于最左侧表示选择根结点的直接子...

学习笔记——XSLT转换器的使用(Xalan和Saxon)

XSLT分为两类: 1:客户端转换:需要浏览器的支持。 2:服务器转换:需要使用编程将XML根据XSLT文档转换成相应的HTML,在输出到客户端。   服务器转换分为两类: 1:实时转换:当...

libevent学习笔记【使用篇】——7. evbuffer:缓冲IO的实用功能

创建和释放evbuffer, Evbuffer和其线程安全性, 直接往evbuffer中添加数据,在Libevent中使用evbuffer最频繁的就是网络IO。网络IO中操作evbuffer的接口如下...
  • Windeal
  • Windeal
  • 2016年10月19日 23:27
  • 1501

MAKEFILE 学习笔记 —— 实用功能

MAKEFILE 学习笔记 —— 实用功能 一. 变量的使用 当我们的程序越来越复杂时,变量的使用可以大大提高我们的效率。makefile 中变量的使用有点类似于 c 语言中的宏...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:学习笔记——XSLT2.0实用的新功能
举报原因:
原因补充:

(最多只允许输入30个字)