XsltArgumentList 类包含 XSLT 参数和 XSLT 扩展对象。传入 Transform 方法后,这些参数和扩展对象可以从样式表中进行调用。

与使用嵌入脚本相比,传递对象具有以下优点:

  • 改善了类的封装和重用。
  • 使样式表可以更小而且更容易维护。 (但是不能动态的修改其中的函数或者是业务,最好还是在样式表添加脚本)
  • 支持调用属于其他命名空间(而不是那些在支持的 System 命名空间集中定义的命名空间)的类的方法。
  • 支持使用 XPathNavigator 将结果树片段传递到样式表。

XSLT 样式表参数

XSLT 参数通过 AddParam 方法添加到 XsltArgumentList。此时,限定名和命名空间 URI 与参数对象关联。

参数对象应对应于 W3C 类型。下表显示了相应的 W3C 类型、等效的 .NET 类(类型),以及 W3C 类型是 XPath 类型还是 XSLT 类型。

W3C 类型等效的 .NET 类(类型)XPath 类型或 XSLT 类型
StringSystem.StringXPath
BooleanSystem.BooleanXPath
NumberSystem.DoubleXPath
结果树片段System.Xml.XPath.XPathNavigatorXSLT
节点集System.Xml.XPath.XPathNodeIteratorXPath

如果参数对象不属于上述类,它将被强制指定为 Double 或 String(以适用的为准)。Int16、UInt16、Int32、UInt32、Int64、UInt64、Single 和 Decimal 类型被强制指定为 Double。所有其他类型均被用 ToString 方法强制指定为 String。

使用用户需要的 XSLT 参数执行以下操作:

  1. 创建 XsltArgumentList 并使用 AddParam 添加对象。
  2. 从样式表调用参数。
  3. XsltArgumentList 传递到 Transform 方法。

示例

下面的示例使用 AddParam 方法创建一个参数来保存计算的折扣日期。折扣日期计算为从订单日期算起的 20 天时间。

 

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

<!--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

<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>

 

输出

 <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 扩展对象执行以下操作:

  1. 创建 XsltArgumentList 并使用 AddExtensionObject 添加扩展对象。
  2. 从样式表调用扩展对象。
  3. XsltArgumentList 传递到 Transform 方法。

示例

已知圆的半径,下面的示例计算圆的周长。

 

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

<?xml version='1.0'?>
<data>
  <circle>
    <radius>12</radius>
  </circle>
  <circle>
    <radius>37.5</radius>
  </circle>
</data>

 

circle.xsl

<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>

 

输出

 

<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>