XSLT2.0新增了许多XSLT1.0不支持的功能.
xsl:function与xsl:result-document属于其新增功能.
xsl:function主要是通过将自定义方法关联到相对应的名称空间,然后通过提供参数以及返回对应结果.
xsl:result-document主要应用是通过在template或者是for-each中对于节点信息进行输出到独立文件.(常见于订单数据的存储以及提取)
以下的代码模拟将一个存储在orders.xml中的订单数据拆分出来.主要用到了以上所说的这两个标签.
存储orders.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet href="orders.xsl" type="text/xsl"?>
<!-- all order records -->
<orders date="2016-08-24"
copyright="®copyright by ricky"
xmlns="http://www.ricky.com/orders"
xmlns:item="http://www.ricky.com/orders/item"
xmlns:consumer="http://www.ricky.com/orders/consumer"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.ricky.com/orders orders.xsd">
<![CDATA[
The following show the orders information.<2016-08-24>
]]>
<order no="201608240001">
<item suk="a000214" quantity="1" stock="BeiJing">
<item:name>
Bikecycle
</item:name>
<mark>
Giant AXT870
</mark>
</item>
<item suk="b031634" quantity="2" stock="ShangHai">
<item:name>
BacketBall
</item:name>
<mark>
<![CDATA[
Wilson && Spalding
]]>
</mark>
</item>
<consumerInfo>
<consumer:name>
Ricky Lin
</consumer:name>
<mobileOrTel>
<mobile>
13988888888
</mobile>
<tel>
0755-828888-3
</tel>
<tel>
0755-88888888-325
</tel>
</mobileOrTel>
<address>
FuTian Area,ShenZhen City,GuangDong Province,China Mainland
</address>
</consumerInfo>
</order>
<!-- order 2 -->
<order no="201608240002">
<item suk="c134103213" quantity="1" stock="ShenZhen">
<item:name>
Computer
</item:name>
<mark>
IBM
</mark>
</item>
<consumerInfo>
<consumer:name>
Jennie Lin
</consumer:name>
<mobileOrTel>
<mobile>
18888888888
</mobile>
<tel>
0755-00000
</tel>
</mobileOrTel>
<address>
ShenZhen.
</address>
</consumerInfo>
</order>
</orders>
<!ELEMENT orders (#PCDATA|order)*>
<!ATTLIST orders date CDATA #REQUIRED>
<!ATTLIST orders copyright CDATA #FIXED "®copyright by ricky">
<!ATTLIST orders xmlns CDATA "http://www.ricky.com/orders">
<!ATTLIST orders xmlns:item CDATA "http://www.ricky.com/orders/item">
<!ATTLIST orders xmlns:consumer CDATA "http://www.ricky.com/orders/consumer">
<!ATTLIST orders xmlns:xsi CDATA #REQUIRED>
<!ATTLIST orders xsi:schemaLocation CDATA #REQUIRED>
<!ELEMENT order (item+,consumerInfo)>
<!ATTLIST order no CDATA #REQUIRED>
<!ELEMENT item (item:name,mark?)>
<!ATTLIST item suk ID #REQUIRED>
<!ATTLIST item quantity CDATA #REQUIRED>
<!ATTLIST item stock (BeiJing|ShangHai|ShenZhen) #IMPLIED>
<!ELEMENT item:name (#PCDATA)>
<!ELEMENT mark (#PCDATA)>
<!ELEMENT consumerInfo (consumer:name,mobileOrTel,address)>
<!ELEMENT consumer:name (#PCDATA)>
<!ELEMENT mobileOrTel (mobile|tel)+>
<!ELEMENT address (#PCDATA)>
<!ELEMENT mobile (#PCDATA)>
<!ELEMENT tel (#PCDATA)>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:orders="http://www.ricky.com/orders" xmlns:item="http://www.ricky.com/orders/item" xmlns:consumer="http://www.ricky.com/orders/consumer" targetNamespace="http://www.ricky.com/orders" elementFormDefault="qualified" attributeFormDefault="unqualified">
<import namespace="http://www.ricky.com/orders/item" schemaLocation="item.xsd"/>
<import namespace="http://www.ricky.com/orders/consumer" schemaLocation="consumer.xsd"/>
<element name="orders" type="orders:OrdersType"/>
<element name="order" type="orders:OrderType"/>
<element name="item" type="orders:ItemType"/>
<element name="consumerInfo" type="orders:ConsumerInfoType"/>
<!-- define orders element -->
<complexType name="OrdersType" mixed="true">
<sequence minOccurs="0" maxOccurs="unbounded">
<element ref="orders:order"/>
</sequence>
<attribute name="date" type="date" use="required"/>
<attribute name="copyright" type="string" use="required" fixed="®copyright by ricky"/>
</complexType>
<!-- define order element -->
<complexType name="OrderType" mixed="false">
<sequence>
<element ref="orders:item" minOccurs="1" maxOccurs="unbounded"/>
<element ref="orders:consumerInfo"/>
</sequence>
<attribute name="no" use="required">
<simpleType>
<restriction base="string">
<pattern value="\d{12}"/>
</restriction>
</simpleType>
</attribute>
</complexType>
<!-- define item element -->
<complexType name="ItemType" mixed="false">
<sequence>
<element ref="item:name"/>
<element name="mark" type="string" minOccurs="0" maxOccurs="1"/>
</sequence>
<attribute name="suk" type="string" use="required"/>
<attribute name="quantity" use="required" type="nonNegativeInteger"/>
<attribute name="stock" use="required">
<simpleType>
<restriction base="string">
<enumeration value="BeiJing"/>
<enumeration value="ShangHai"/>
<enumeration value="ShenZhen"/>
</restriction>
</simpleType>
</attribute>
</complexType>
<!-- define consumerInfo element -->
<complexType name="ConsumerInfoType" mixed="false">
<sequence>
<element ref="consumer:name"/>
<element name="mobileOrTel">
<!-- define mobileOrTel element -->
<complexType mixed="false">
<sequence minOccurs="1" maxOccurs="unbounded">
<choice>
<element name="mobile">
<simpleType>
<union>
<simpleType>
<restriction base="string">
<pattern value="\s*([+]?\d+\s+)?1\d{10}\s*"/>
</restriction>
</simpleType>
<simpleType>
<restriction base="string">
<enumeration value="Unknow"/>
</restriction>
</simpleType>
<simpleType>
<restriction base="string">
<pattern value="\s*Unknow\s*"/>
</restriction>
</simpleType>
</union>
</simpleType>
</element>
<element name="tel">
<simpleType>
<union>
<simpleType>
<restriction base="string">
<pattern value="\s*([+]?\d+\s+)?\d+(-\d+){0,2}\s*"/>
</restriction>
</simpleType>
<simpleType>
<restriction base="string">
<enumeration value="Unknow"/>
</restriction>
</simpleType>
<simpleType>
<restriction base="string">
<pattern value="\s*Unknow\s*"/>
</restriction>
</simpleType>
</union>
</simpleType>
</element>
</choice>
</sequence>
</complexType>
</element>
<element name="address" type="string"/>
</sequence>
</complexType>
</schema>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.ricky.com/orders/item"
xmlns:item="http://www.ricky.com/orders/item"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<element name="name" type="string"/>
</schema>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.ricky.com/orders/consumer"
xmlns:consumer="http://www.ricky.com/orders/consumer"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<element name="name" type="string"/>
</schema>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:orders="http://www.ricky.com/orders"
xmlns:item="http://www.ricky.com/orders/item"
xmlns:consumer="http://www.ricky.com/orders/consumer"
xmlns:myFunction="http://www.ricky.com/myFunction"
xmlns:myData="http://www.ricky.com/myData"
exclude-result-prefixes="xs orders item consumer myFunction myData">
<xsl:variable name="thisDocument" select="document('')"/>
<xsl:variable name="ordersData" select="document('orders.xml')"/>
<xsl:template match="/">
<html>
<head>
<title>
<xsl:value-of select="$ordersData/orders:orders/text()[1]"/>
</title>
</head>
<body>
<h3>
<xsl:value-of select="$ordersData/orders:orders/text()[1]"/>
</h3>
<hr/>
<xsl:apply-templates select="$ordersData/orders:orders/orders:order" mode="menu">
<xsl:sort select="@no" data-type="number"/>
</xsl:apply-templates>
<hr/>
<table>
<thead>
<th>
OrderNo
</th>
<th>
ItemDetail
</th>
<th>
consumerInfo
</th>
<th>
Address
</th>
</thead>
<tbody>
<xsl:apply-templates select="$ordersData/orders:orders/orders:order" mode="separateSave"/>
<xsl:apply-templates select="$ordersData/orders:orders/orders:order" mode="showDetail"/>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="orders:order" mode="menu">
<a href="#order{@no}">
<xsl:value-of select="@no"/>
</a>
<<xsl:value-of select="orders:consumerInfo/consumer:name"/>>
<br/>
</xsl:template>
<xsl:template match="orders:order" mode="separateSave">
<!-- remove tab -->
<xsl:variable name="consumerNameWithoutTab" select="myFunction:replaceAll(orders:consumerInfo/consumer:name,'
')"/>
<!-- remove line feed-->
<xsl:variable name="consumerNameWithoutLine" select="myFunction:replaceAll($consumerNameWithoutTab,' ')"/>
<!-- remove space -->
<xsl:variable name="consumerName" select="myFunction:replaceAll($consumerNameWithoutLine,' ')"/>
<!-- ouput file name: orderNo-consumerName.html -->
<xsl:result-document href="{concat(@no,'-',$consumerName)}.html">
<html>
<head>
<title>
<xsl:value-of select="concat('Order-',@no,' Information')"/>
</title>
</head>
<body>
<h3>
<xsl:value-of select="myFunction:formatDate(../@date)"/>:<xsl:value-of select="@no"/>
</h3>
<hr/>
consumerInfo:<xsl:apply-templates select="orders:consumerInfo"/>
<hr/>
<table>
<thead>
<th>
ItemName
</th>
<th>
SUK
</th>
<th>
Quantity
</th>
<th>
Stock
</th>
<th>
Mark
</th>
</thead>
<tbody>
<xsl:apply-templates select="orders:item" mode="signalShow">
<xsl:sort select="@stock" data-type="text"/>
</xsl:apply-templates>
</tbody>
</table>
</body>
</html>
</xsl:result-document>
</xsl:template>
<xsl:template match="orders:item" mode="signalShow">
<tr>
<td>
<xsl:value-of select="item:name"/>
</td>
<td>
<xsl:value-of select="@suk"/>
</td>
<td>
<center>
<xsl:value-of select="@quantity"/>
</center>
</td>
<td>
<xsl:value-of select="@stock"/>
</td>
<td>
<xsl:value-of select="orders:mark"/>
</td>
</tr>
</xsl:template>
<xsl:template match="orders:order" mode="showDetail">
<xsl:apply-templates select="orders:item"/>
</xsl:template>
<xsl:template match="orders:item">
<tr>
<td>
<xsl:if test="position() = 1">
<a name="order{../@no}">
<xsl:value-of select="../@no"/>
</a>
</xsl:if>
</td>
<td>
<xsl:apply-templates select="." mode="showItem"/>
</td>
<td>
<xsl:if test="position() = 1">
<xsl:apply-templates select="../orders:consumerInfo"/>
</xsl:if>
</td>
<td>
<xsl:if test="position() = 1">
<xsl:value-of select="../orders:consumerInfo/orders:address"/>
</xsl:if>
</td>
</tr>
</xsl:template>
<xsl:template match="orders:item" mode="showItem">
<strong>
<xsl:value-of select="item:name"/>
</strong>
<xsl:call-template name="showAttributes">
<xsl:with-param name="attrs" select="@*"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="orders:consumerInfo">
<strong>
<xsl:value-of select="consumer:name"/>
</strong>
[
<xsl:for-each select="orders:mobileOrTel/*">
<xsl:variable name="fontColor">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">red</xsl:when>
<xsl:otherwise>black</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<font color="{$fontColor}">
<xsl:value-of select="."/>
</font>
<xsl:if test="position() != last()">
,
</xsl:if>
</xsl:for-each>
]
</xsl:template>
<xsl:template name="showAttributes">
<xsl:param name="attrs"/>
<xsl:if test="count($attrs) > 0">
[
<xsl:for-each select="$attrs">
<xsl:variable name="fontColor">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">red</xsl:when>
<xsl:otherwise>blue</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<font color="{$fontColor}">
<xsl:value-of select="concat(name(),':',.)"/>
</font>
</xsl:for-each>
<xsl:if test="position() != last()">
,
</xsl:if>
]
</xsl:if>
</xsl:template>
<xsl:function name="myFunction:replaceAll" as="xs:string">
<xsl:param name="content" as="xs:string"/>
<xsl:param name="replace" as="xs:string"/>
<xsl:choose>
<xsl:when test="contains($content,$replace)">
<xsl:variable name="before" select="substring-before($content,$replace)"/>
<xsl:variable name="after" select="substring-after($content,$replace)"/>
<xsl:variable name="newContent" select="concat($before,$after)"/>
<xsl:value-of select="myFunction:replaceAll($newContent,$replace)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$content"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="myFunction:formatDate" as="xs:string">
<xsl:param name="iso8601Date" as="xs:date"/>
<xsl:variable name="yearPart" select="year-from-date($iso8601Date)" as="xs:integer"/>
<xsl:variable name="monthPart" select="month-from-date($iso8601Date)" as="xs:integer"/>
<xsl:variable name="datePart" select="day-from-date($iso8601Date)" as="xs:integer"/>
<xsl:variable name="monthName" select="$thisDocument/xsl:stylesheet/myData:months/month[number(@index) = number($monthPart)]" as="xs:string"/>
<xsl:value-of select="concat($datePart,' ',$monthName,' ',$yearPart)"/>
</xsl:function>
<!-- define month names -->
<myData:months>
<month index="1">January</month>
<month index="2">February</month>
<month index="3">March</month>
<month index="4">April</month>
<month index="5">May</month>
<month index="6">June</month>
<month index="7">July</month>
<month index="8">Auguest</month>
<month index="9">September</month>
<month index="10">October</month>
<month index="11">November</month>
<month index="12">December</month>
</myData:months>
</xsl:stylesheet>