XsltArgumentList 类包含 XSLT 参数和 XSLT 扩展对象。传入 Transform 方法后,这些参数和扩展对象可以从样式表中进行调用。
与使用嵌入脚本相比,传递对象具有以下优点:
- 改善了类的封装和重用。
- 使样式表可以更小而且更容易维护。 (但是不能动态的修改其中的函数或者是业务,最好还是在样式表添加脚本)
- 支持调用属于其他命名空间(而不是那些在支持的 System 命名空间集中定义的命名空间)的类的方法。
- 支持使用 XPathNavigator 将结果树片段传递到样式表。
XSLT 样式表参数
XSLT 参数通过 AddParam 方法添加到 XsltArgumentList。此时,限定名和命名空间 URI 与参数对象关联。
参数对象应对应于 W3C 类型。下表显示了相应的 W3C 类型、等效的 .NET 类(类型),以及 W3C 类型是 XPath 类型还是 XSLT 类型。
W3C 类型 | 等效的 .NET 类(类型) | XPath 类型或 XSLT 类型 |
---|---|---|
String | System.String | XPath |
Boolean | System.Boolean | XPath |
Number | System.Double | XPath |
结果树片段 | System.Xml.XPath.XPathNavigator | XSLT |
节点集 | System.Xml.XPath.XPathNodeIterator | XPath |
如果参数对象不属于上述类,它将被强制指定为 Double 或 String(以适用的为准)。Int16、UInt16、Int32、UInt32、Int64、UInt64、Single 和 Decimal 类型被强制指定为 Double。所有其他类型均被用 ToString 方法强制指定为 String。
使用用户需要的 XSLT 参数执行以下操作:
- 创建 XsltArgumentList 并使用 AddParam 添加对象。
- 从样式表调用参数。
- 将 XsltArgumentList 传递到 Transform 方法。
示例
下面的示例使用 AddParam 方法创建一个参数来保存计算的折扣日期。折扣日期计算为从订单日期算起的 20 天时间。
[Visual Basic]
Imports System
Imports System.IO
Imports System.Xml
Imports System.Xml.XPath
Imports System.Xml.Xsl
Public class Sample
Private Const filename As String = "order.xml"
Private Const stylesheet As String = "discount.xsl"
Public Shared Sub Main()
'Create the XslTransform and load the stylesheet.
Dim xslt As XslTransform = New XslTransform
xslt.Load(stylesheet)
'Load the XML data file.
Dim doc As XPathDocument = New XPathDocument(filename)
'Create an XsltArgumentList.
Dim xslArg As XsltArgumentList = New XsltArgumentList
'Calculate the discount date.
Dim today As DateTime = DateTime.Now
Dim d As DateTime = today.AddDays(20)
xslArg.AddParam("discount", "", d.ToString())
'Create an XmlTextWriter to handle the output.
Dim writer As XmlTextWriter = New XmlTextWriter("orderout.xml", Nothing)
'Transform the file.
xslt.Transform(doc, xslArg, writer, Nothing)
writer.Close()
End Sub
End Class
[C#]
using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
public class Sample
{
private const String filename = "order.xml";
private const String stylesheet = "discount.xsl";
public static void Main() {
//Create the XslTransform and load the stylesheet.
XslTransform xslt = new XslTransform();
xslt.Load(stylesheet);
//Load the XML data file.
XPathDocument doc = new XPathDocument(filename);
//Create an XsltArgumentList.
XsltArgumentList xslArg = new XsltArgumentList();
//Calculate the discount date.
DateTime today = DateTime.Now;
DateTime d = today.AddDays(20);
xslArg.AddParam("discount", "", d.ToString());
//Create an XmlTextWriter to handle the output.
XmlTextWriter writer = new XmlTextWriter("orderout.xml", null);
//Transform the file.
xslt.Transform(doc, xslArg, writer, null);
writer.Close();
}
}
输入
order.xml
[Visual Basic, C#]
<!--Represents a customer order-->
<order>
<book ISBN='10-861003-324'>
<title>The Handmaid's Tale</title>
<price>19.95</price>
</book>
<cd ISBN='2-3631-4'>
<title>Americana</title>
<price>16.95</price>
</cd>
</order>
discount.xsl
[Visual Basic, C#]
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="discount"/>
<xsl:template match="/">
<order>
<xsl:variable name="sub-total" select="sum(//price)"/>
<total><xsl:value-of select="$sub-total"/></total>
15% discount if paid by: <xsl:value-of select="$discount"/>
</order>
</xsl:template>
</xsl:stylesheet>
输出
[Visual Basic, C#]
<order>
<total>36.9</total>
15% discount if paid by: 5/6/2001 5:01:15 PM
</order>
XSLT 扩展对象
XSLT 扩展对象通过 AddExtensionObject 方法添加到 XsltArgumentList。此时,限定名和命名空间 URI 与扩展对象关联。
添加对象时,AddExtensionObject 的调用方在安全策略中必须是完全受信任的。如果调用方不是完全受信任的,则添加操作将失败。
尽管对象已成功添加,但它不能保证执行将成功。调用 Transform 方法时,将针对在 Load 时提供的证据来计算权限,并且将权限集分配给整个转换进程。如果一个扩展对象尝试启动一个操作,而该操作需要权限集中所没有的权限,就会引发异常。
从扩展对象返回的数据类型是四种 XPath 基本数据类型之一:数字、字符串、布尔值或节点集。
使用用户需要的 XSLT 扩展对象执行以下操作:
- 创建 XsltArgumentList 并使用 AddExtensionObject 添加扩展对象。
- 从样式表调用扩展对象。
- 将 XsltArgumentList 传递到 Transform 方法。
示例
已知圆的半径,下面的示例计算圆的周长。
[Visual Basic]
Imports System
Imports System.IO
Imports System.Xml
Imports System.Xml.XPath
Imports System.Xml.Xsl
Public Class Sample
Private Const filename As String = "number.xml"
Private Const stylesheet As String = "circle.xsl"
Public Shared Sub Main()
Dim test As Sample = New Sample
End Sub
Public Sub New()
'Create the XslTransform and load the stylesheet.
Dim xslt As XslTransform = New XslTransform
xslt.Load(stylesheet)
'Load the XML data file.
Dim doc As XPathDocument = New XPathDocument(filename)
'Create an XsltArgumentList.
Dim xslArg As XsltArgumentList = New XsltArgumentList
'Add an object to calculate the circumference of the circle.
Dim obj As Calculate = New Calculate
xslArg.AddExtensionObject("urn:myObj", obj)
'Create an XmlTextWriter to output to the console.
Dim writer As XmlTextWriter = New XmlTextWriter(Console.Out)
'Transform the file.
xslt.Transform(doc, xslArg, writer, Nothing)
writer.Close()
End Sub
'Calculates the circumference of a circle given the radius.
Public Class Calculate
Private circ As double = 0
Public Function Circumference(radius As Double) As Double
circ = Math.PI*2*radius
Return circ
End Function
End Class
End Class
[C#]
using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
public class Sample
{
private const String filename = "number.xml";
private const String stylesheet = "circle.xsl";
public static void Main() {
Sample test = new Sample();
}
public Sample() {
//Create the XslTransform and load the stylesheet.
XslTransform xslt = new XslTransform();
xslt.Load(stylesheet);
//Load the XML data file.
XPathDocument doc = new XPathDocument(filename);
//Create an XsltArgumentList.
XsltArgumentList xslArg = new XsltArgumentList();
//Add an object to calculate the circumference of the circle.
Calculate obj = new Calculate();
xslArg.AddExtensionObject("urn:myObj", obj);
//Create an XmlTextWriter to output to the console.
XmlTextWriter writer = new XmlTextWriter(Console.Out);
//Transform the file.
xslt.Transform(doc, xslArg, writer, null);
writer.Close();
}
//Calculates the circumference of a circle given the radius.
public class Calculate{
private double circ = 0;
public double Circumference(double radius){
circ = Math.PI*2*radius;
return circ;
}
}
}
输入
number.xml
[Visual Basic, C#]
<?xml version='1.0'?>
<data>
<circle>
<radius>12</radius>
</circle>
<circle>
<radius>37.5</radius>
</circle>
</data>
circle.xsl
[Visual Basic, C#]
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myObj="urn:myObj">
<xsl:template match="data">
<circles>
<xsl:for-each select="circle">
<circle>
<xsl:copy-of select="node()"/>
<circumference>
<xsl:value-of select="myObj:Circumference(radius)"/>
</circumference>
</circle>
</xsl:for-each>
</circles>
</xsl:template>
</xsl:stylesheet>
输出
[Visual Basic, C#]
<circles xmlns:myObj="urn:myObj">
<circle>
<radius>12</radius>
<circumference>75.398223686155</circumference>
</circle>
<circle>
<radius>37.5</radius>
<circumference>235.61944901923448</circumference>
</circle>
</circles>