.Net框架下的XSLT转换技术简介 【转】

一.前言:

  xslt转换技术是xml中的一项重要技术,本文将向xml研发者介绍.net框架下的一些不同的xslt转换技术。同 时,本文还将介绍怎么运用各种不同的输入数据源以完成一个xslt转换。在.net框架下,system.xml.xsl.xsltransform类能 根据一个xslt样式表文件转换一个xml文件,他是xslt转换中最重要的一个类,同时他能够支持w3c的xslt 1.0的语法,其运用的命名空间是http://www.w3.org/1999/xsl/transform。

  二.和xslt转换相关的输入数据源:

   .net框架下有许多类能完成读取xml文件以实现xslt转换的功能,其中最有用的当属system.xml.xmlreader类了。他是个虚基 类,因此不能被直接运用,必须有一个类继承他。.net框架下有三个类是从该类继承过来的:xmltextreader类、xmlnodereader类 及xmlvalidatingreader类,他们都是包含在命名空间system.xml中的。其中xmltextreader类能从一个xml文件中 读取字符流并检查该文件是否是具有良好结构(well-formed)的,但他并不运用dtd或是xml模式进行xml文件的验证工作。 xmlnodereader类允许数据从所有xml文件对象模型(dom)的api中被读取,比如一个system.xml.xmlnode对象,而且 xmlnode对象并不必是个完整的xml文件的根节点,他能是其一个子节点。xmlvalidatingreader类能确保一个xml文件是遵从一个 dtd或是xml模式所确定的规则的。下面是个xmlreader类作为xslt转换的输入数据源的应用实例。

  // 将一个xslt文件的字符串导入到一个textreader对象中
  system.io.textreader tr = new system.io.streamreader("numbers.xsl");
  // 将上面的textreader对象作为xmltextreader对象的数据源
  system.xml.xmlreader xr = new system.xml.xmltextreader(tr);
  // 创建一个新的xsltransform对象
  system.xml.xsl.xsltransform trans = new system.xml.xsl.xsltransform();
  // 将xmlreader对象中的样式表导入到上面的xsltransform对象中
  trans.load(xr);



   另一种能完成读取xml文件以实现xslt转换功能的类是system.xml.xpath.xpathnavigator类或是所有实现了 system.xml.xpath.ixpathnavigable接口的类,这些类包括了 system.xml.xpath.xpathdocument类,system.xml.xmldocument类及 system.xml.xmldatadocument类。system.xml.xpath.xpathnavigator类是基于xpath数据模型 的,并提供了能够对所有xml数据进行xpath查询的方法。

  system.xml.xpath.xpathdocument类是 这些类中速度最快的一个类,因为他是只读的,在xslt转换对速度的需求非常高时应该使用这个类。system.xml.xmldocument类的效率 仅次于system.xml.xpath.xpathdocument类,而system.xml.xmldatadocumnet类并不适合xslt转 换,因为他的效率最低。system.xml.xpath.ixpathnavigable接口能在所有数据源上实现,同时他允许所有类型的数据作为 xslt转换的数据源。下面的示例代码能被接在上面的例子后面。

  // 创建一个新的xpathdocument对象,并从一个xml文件导入数据源

  system.xml.xpath.xpathdocument xp = new

  system.xml.xpath.xpathdocument("numbers.xml");

  // 创建一个新的xpathnavigator对象

  system.xml.xpath.xpathnavigator xpn = xp.createnavigator();

   xsltransform类需求xml或xslt的数据源是个xmlreader对象或是个xpathnavigator对象。他的两个最重要的方法是 load()方法和transform()方法,这两个方法并不提供重载的对stream对象直接进行处理的方法,不过却能间接地将stream对象作为 xslt转换的数据源,而该stream对象则是从xml文件或xslt样式表中获取的。下面的代码创建了一个stream对象,并显示了怎么将他作为 xslt转换的数据源,不过该代码段仅仅是个示例,并没有实际的数据存在。

  // 创建一个新的stream对象

  system.io.stream st = new system.io.memorystream();

  // 在此运用一个xml文件填充上面的stream对象并将stream对象的位置置为0

  st.position = 0;

  // 将stream对象导入到一个xpathdocument对象中

  system.xml.xpath.xpathdocument xp = new system.xml.xpath.xpathdocument(st);

  // 对xslt文件进行同样的操作

  system.io.stream xsltstream = new system.io.memorystream();

  // 在此运用一个xslt文件填充上面的stream对象并将stream对象的位置置为0

  st.position = 0;

  // 创建一个xmlreader对象,并将上面的stream对象作为数据源

  system.xml.xmlreader xsltxr = new system.xml.xmltextreader(xsltstream);

  // 以后,该xmlreader对象就能被传递到xsltransform类的load()方法中去了

   上面的代码中并没有实际的数据存在,我们需要将xml文件或xslt样式表填充到stream对象中才能进行实际的操作。另一种设置输入数据源的方法是 以字符串的形式从一个url获取xml文件或xslt文件,同时还可能有一个可选择的system.xml.xmlresolver对象,该方法是最直接 也是最有效的方法。

  三.和xslt转换相关的输出数据源:

  在介绍了xslt转换的输入数据源之后,本文接着 向大家介绍和之相关的输出数据源。根据所运用的不同类型的输出类,xsl:output元素有时能被忽略掉。比如在运用xmlwriter类或 xmlreader类作为输出类的时候,该元素就被忽略掉了。有关xsl:output元素的周详内容请参考msdn的文章"outputs from an xsltransform",这里限于篇幅就不多作介绍了。

  综上所述,进行xslt转换的必要条件包括了一个xml文件,一个xslt文件及一个能处理输出的有效对象。下面的代码运用了一个xpathdocument对象及一个样式表文件进行xslt转换,其输出的结果被直接显示在控制台中了。

  // 创建一个新的xsltransform对象

  system.xml.xsl.xsltransform xslt = new system.xml.xsl.xsltransform();

  // 从xsl文件中导入样式表

  xslt.load("numbers.xsl");

  // 创建一个新的xpathdocument对象,并导入一个xml文件

  system.xml.xpath.xpathdocument doc = new

  system.xml.xpath.xpathdocument("numbers.xml");

  // 创建一个新的xmltextwriter对象用于完成到控制台的数据输出

  system.xml.xmltextwriter writer = new

   system.xml.xmltextwriter(system.console.out);

  // 进行实际的xslt转换操作

  xslt.transform(doc, null, writer);

  // 在完成操作后关闭xmltextwriter对象

  // 同时请注意一旦关闭该对象就不能往控制台中写所有额外信息了

  writer.close();

  四.和xslt转换相关的流对象:

  .net框架允许程式员将xslt转换的结果直接输出到一个system.io.stream对象,下面的代码将使用一个用于输出的system.io.memorystream对象,然后显示怎么运用他进行和xslt转换的输出相关的操作。

  // 创建一个新的xsltransform对象

  system.xml.xsl.xsltransform xslt = new system.xml.xsl.xsltransform();

  // 从xslt文件中导入样式表

  xslt.load("numbers.xsl");

  // 导入一个xml文件

  system.xml.xpath.xpathdocument doc = new

   system.xml.xpath.xpathdocument("numbers.xml");

  // 创建用于输出的stream对象

  system.io.stream str = new system.io.memorystream();

  // 进行实际的转换操作

  xslt.transform(doc, null, str);

  // 对stream对象进行flush操作,并将其位置置为0

  str.flush();

  str.position = 0;

   如果一个system.xml.xmldocument对象或一个system.xml.xpath.xpathdocument对象已被载入到主存中 了,那么他们也能被用作xslt转换的输入数据源。因为这两个对象都实现了system.xml.xpath.ixpathnavigable接口,所以 都能作为xsltransform对象的transform()方法的参数被直接使用。

  // 创建一个新的xsltransform对象

  system.xml.xsl.xsltransform xslt = new system.xml.xsl.xsltransform();

  // 从xslt文件中导入样式表

  xslt.load("numbersxml.xsl");

  // 将一个xml文件导入到一个xpathdocument对象中

  system.xml.xpath.xpathdocument doc = new

   system.xml.xpath.xpathdocument("numbers.xml");

  // 创建用于输出的stream对象

  system.io.stream str = new system.io.memorystream();

  system.xml.xmlwriter xw = new

   system.xml.xmltextwriter(str,system.text.encoding.utf8);

  // 进行实际的转换操作

  xslt.transform(doc, null, xw);

  // 对xmlwriter对象进行flush操作,并将stream对象的位置置为0

  xw.flush();

  str.position = 0;

  五.和xslt转换相关的嵌入式脚本及代码:

   .net框架中的xslt转换对象提供了对在xslt文件中用脚本扩展元素来嵌入脚本语言的支持。脚本语言所提供的一组功能比纯xslt所提供的功能要 丰富,经常能用来对文件内容进行更为复杂的操作,比如对其应用科学计算函数、访问外部信息源等。在.net框架下,程式员运用msxsl:script元 素能标记xslt样式表中的嵌入式脚本或代码。脚本扩展元素必须在urn:schemas-microsoft-com:xslt namespace命名空间中声明。.net框架中的分析器能够支持c#、vb.net、vbscript或jscript等代码编写的脚本。在脚本元素 中,我们通过提供一个implements-prefix属性定义了函数所调用的命名空间,通过提供一个language属性定义了函数所使用的编程语 言。同时,我们得注意一个样式表中能嵌入多种语言的脚本代码,不过同一个命名空间下只能使用同一种语言。下面的实例显示了一个包含嵌入式c#函数的样式 表。

<xsl:stylesheet version=1.0
xmlns:xsl=http://www.w3.org/1999/xsl/transform
xmlns:msxsl=urn:schemas-microsoft-com:xslt
xmlns:thescript=urn:customscript>
<xsl:output omit-xml-declaration=yes method=text
media-type=text/plain indent=no />
<xsl:variable name=displayme />

<msxsl:script implements-prefix=thescript language=c#>
<![cdata[
public string helloname(string name)
{
return "hello " + name;
}
]]>
</msxsl:script>

<xsl:template match=/>
<xsl:text disable-output-escaping=yes>print integers > 3</xsl:text>
<xsl:apply-templates select=root/numbers />
script result: <xsl:value-of select=thescript:helloname("joe") />
done: <xsl:value-of select=$displayme />
</xsl:template>

<xsl:template match=numbers>
numbers:<xsl:apply-templates select=integer[@value > 3] />
</xsl:template>

<xsl:template match=integer>
integer: <xsl:value-of select=@value />
</xsl:template>
</xsl:stylesheet>



  六.样式表参数及扩展对象:

   xslt提供了一个在样式表中使用参数及扩展对象的机制。在.net框架下,程式员能通过运用 system.xml.xsl.xsltargumentlist类实现将参数或扩展对象传递到一个样式表。在样式表中使用参数的机制允许程式员声明一个 全局变量,该变量被定义为xsl:variable类型的元素,他是作为一个xsl:stylesheet的子元素而存在的,但他并不包含在 xsl:template之中。通过调用xsltargumentlist类的addparam()方法程式员能实现添加参数的功能,该方法中的三个参数 依次为有效的名称、命名空间的uri及参数值。如果参数值不是个字符串、布尔值、数字、节点片断(node fragment)或节点集合(node set),那么他将被强制转化为双精度浮点值或是字符串。而一个扩展对象是所有一个能返回xslt数据类型值的.net类。通过调用 xsltargumentlist类的addextensionobject()方法程式员能实现添加扩展对象的功能,该方法中的两个参数分别为有效的名 称及命名空间的uri。下面的代码显示了怎么运用xsltargumentlist类在样式表中使用参数及扩展对象的方法。

  // 创建一个新的xpathdocument对象,并导入一个xml文件

  system.xml.xpath.xpathdocument xp = new

   system.xml.xpath.xpathdocument("numbers.xml");

  // 创建一个新的xsltransform对象

  system.xml.xsl.xsltransform trans = new system.xml.xsl.xsltransform();

  // 导入一个xslt文件到上面的xsltransform对象中

  trans.load("numbersextension.xsl");

  // 创建一个新的xsltargumentlist对象

  system.xml.xsl.xsltargumentlist xslarg = new

   system.xml.xsl.xsltargumentlist();

  // 调用xsltargumentlist对象的addparam()方法以添加参数

  xslarg.addparam("displayme","","is this fun?");

  // 创建一个新的扩展对象

  sayhello hi = new sayhello();

  // 调用xsltargumentlist对象的addextensionobject()方法以添加扩展对象

  xslarg.addextensionobject("urn:sayhello",hi);

  // 创建一个新的system.io.stream对象以处理输出结果

  system.io.stream str = new system.io.memorystream();

  // 进行实际的转换操作

  trans.transform(xp, xslarg, str);

  // 对stream对象进行flush操作,并将其位置置为0

  str.flush();

  str.position = 0;

  // 创建一个新的streamreader对象以读取流并返回字符串

  system.io.streamreader sr = new system.io.streamreader(str);

  string xmlout = sr.readtoend();

  // 关闭streamreader 对象

  sr.close();

  // 将结果写到控制台中

  console.write(xmlout);

  // 扩展对象返回hello name

  public class sayhello  

  {

   public string helloname(string name) {

   return "hello " + name;

  }

  }

  通过上面的介绍,我们发现使用扩展对象和使用嵌入式脚本具有许多相同之处。下面我们分析一下使用扩展对象相对于使用嵌入式脚本的一些优缺点。

   移植性:嵌入式脚本比扩展对象更容易移植,因为所有.net平台都能正确地用嵌入式脚本来转换一个样式表。而另一方面,使用扩展对象的样式表则只能用一 段代码来进行转换,而且需在.net平台或其他一些支持扩展对象的平台下进行,并需求这段代码能正确地实现一个带有效的名称和命名空间uri的扩展对象。

  大小:一个依赖于扩展对象的样式表比包含嵌入式脚本的样式表要小,而且更容易维护。

  灵活性:正如我们看到的那样,依赖于扩展对象的样式表能按照修改约束他们的扩展对象的功能来修改他们的行为。而使用嵌入式脚本的样式表则永远只能按照嵌入的脚本语言指定的功能执行操作。

  性能:因为扩展对象是预编译的,而不是即时编译的,因此使用扩展对象的脚本的性能在某种程度上要比嵌入式脚本高一些。不过具体情况下还要考虑装入样式表的频率及嵌入式脚本的规模等因素。

  可维护性:使用扩展对象的样式表在修改和纠错时可能比较困难,因为真正的代码从样式表和提供扩展对象实现的代码中分离出去了。而嵌入式脚本尽管稍微慢一些,却具有将所有代码都置于本地的好处。

  通过考虑上述一些因素,我们能决定在具体的情况下是使用扩展对象还是使用嵌入式脚本了。

  七.总结:

   本文向大家介绍了.net框架下和xslt转换相关的一些知识,xslt转换技术是xml中的一项重要技术。.net框架对xslt转换提供了稳健的支 持,他不仅完全支持w3c定义的xslt规范,更有许多有用的扩展,比如在样式表中嵌入多种语言的脚本、使用扩展对象来扩展xslt的功能等等,从而增强 了.net应用程式中样式表的易用性。最后,我希望大家能通过本文掌控.net框架有关xslt转换的一些基本技术,并了解每种技术的优缺点以更好地应用 于实际的项目。

原文地址:https://www.cnblogs.com/lxiang/p/2654597.html