C#高级编程之处理XML-连载十二

时间:2010年04月12日 点击:238

23.7.2  System.Xml.Xsl命名空间

System.Xml.Xsl命名空间包含.NET Framework用于支持XSL Transform类。这个命名空间中的类可以和任何实现IXPathNavigable接口的存储器一起使用。在目前的.NET Framework中,包含XmlDocumentXmlDataDocument XPathDocument。与XPath一样,应使用最有效的存储器。如果计划创建一个定制存储器,例如文件系统,并进行一定的转换,就应在类中实现IXPathNavigable接口。

XSL建立在一个流拉模式(streaming pull mode)上。因此,可以把几个转换链接在一起。如果需要,甚至可以在转换之间应用一个定制阅读器,这样在设计时就会有很大的灵活性。

1. 转换XML

第一个示例获取books.xml文档,并使用XSLT文件book.xsl把它转换为一个简单的HTML文档,以进行显示(这段代码在XPathXSLSample3文件夹中),需要添加如下using语句:

using System.IO;

using System.Xml.Xsl;

using System.Xml.XPath;

下面是执行转换的代码:

private void button1_Click(object sender, System.EventArgs e)

{

   //create the new XPathDocument

   XPathDocument doc = new XPathDocument("..\\..\\..\\booksxpath.xml");

   //create a new XslTransForm

   XslTransform transForm = new XslTransform();

   transForm.Load("..\\..\\..\\books.xsl");

   //this FileStream will be our output

   FileStream fs=new FileStream("..\\..\\..\\booklist.html",

                                 FileMode.Create);

   //Create the navigator

   XPathNavigator nav = doc.CreateNavigator();

   //Do the transform. The output file is created here

   transForm.Transform(nav, null, fs);

}

这就是一个简单的转换。创建一个基于XPathDocument的对象和一个基于XslTransform对象。把booksxpath.xml文件加载到XPathDocument上,把books.xsl文件加载到XslTransform上。

在本例中,再创建一个FileStream对象,把新HTML文档写入磁盘。如果这是一个ASP.NET应用程序,就可以使用TextWriter对象,把它传递给HttpResponse对象。如果要转换为另一个XML文档,就可以使用一个基于XmlWriter的对象。

准备好XPathDocument XslTransform对象后,就在XPathDocument上创建XPathNavigator,并把XPathNavigatorFliestream传送给XslTransForm对象的Transform方法。Transform()有几个重载方法,其参数是浏览器、XsltArgumentList (详见后面的讨论)IO流和XmlResolver的组合。浏览器参数可以是XPathNavigator或执行IXPathNavigable接口的其他对象。IO流可以是基于TextWriterStreamXmlWriter的对象。XmlResolver处理安全性,打开数据源,返回数据或流。在.NET Framework 1.0中,XmlResolver参数不是必须的。TransForm方法的所有版本都受到非议,现在XmlResolver参数是必须的,但如果不需要XmlResolver的特性即安全性和凭证管理,可以把它设置为null

books.xsl文档是一个很简单的样式表,如下所示:

<xsl:stylesheet version="1.0"

                      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

   <html>

      <head>

         <title>Price List</title>

      </head>

      <body>

         <table>

            <xsl:apply-templates/>

         </table>     

      </body> 

   </html> 

    </xsl:template>

   <xsl:template match="bookstore">

      <xsl:apply-templates select="book"/>

   </xsl:template>

   <xsl:template match="book">

      <tr><td>

         <xsl:value-of select="title"/>

      </td><td>

         <xsl:value-of select="price"/>

      </td></tr>

   </xsl:template>

</xsl:stylesheet>

使用XsltArgumentList

前面提到了XsltArgumentList,这是把对象和方法绑定到命名空间上的一种方式。绑定好后,就可以在转换过程中调用该方法。下面的示例说明了它的具体工作方式(XPathXSLSample4)。将下面突出显示的代码添加到示例代码中:

private void button1_Click(object sender, System.EventArgs e)

{

   //new XPathDocument

   XPathDocument doc=new XPathDocument("..\\..\\..\\booksxpath.xml");

   //new XslTransform

   XslTransform transForm=new XslTransform();

   transForm.Load("..\\..\\..\\booksarg.xsl");

   //new XmlTextWriter since we are creating a new XML document

   XmlWriter xw=new XmlTextWriter("..\\..\\..\\argSample.xml",null);

   //create the XsltArgumentList and new BookUtils object

   XsltArgumentList argBook=new XsltArgumentList();

   BookUtils bu=new BookUtils();

   //this tells the argumentlist about BookUtils

   argBook.AddExtensionObject("urn:ProCSharp",bu);

   //new XPathNavigator

   XPathNavigator nav=doc.CreateNavigator();

   //do the transform

   transForm.Transform(nav,argBook,xw);

   xw.Close();

}

//simple test class

public class BookUtils

{

   public BookUtils(){}

  

   public string ShowText()

   {

      return "This came from the ShowText method!";

   }

}

下面是转换的结果。其结果已进行了格式化,以便于查看(argSample.xml)

<books>

   <discbook>

      <booktitle>The Autobiography of Benjamin Franklin</booktitle>

      <showtext>This came from the ShowText method!</showtext>

   </discbook>

   <discbook>

      <booktitle>The Confidence Man</booktitle>

      <showtext>This came from the ShowText method!</showtext>

   </discbook>

   <discbook>

      <booktitle>The Gorgias</booktitle>

      <showtext>This came from the ShowText method!</showtext>

   </discbook>

   <discbook>

      <booktitle>The Great Cookie Caper</booktitle>

      <showtext>This came from the ShowText method!</showtext>

   </discbook>

   <discbook>

      <booktitle>A Really Great Book</booktitle>

      <showtext>This came from the ShowText method!</showtext>

   </discbook>

</books>

在本例中,我们定义一个新类BookUtils。在这个类中有一个不起作用的方法,它返回字符串This came from the ShowText method!。在button1_Click事件中,像以前一样创建XPathDocument XslTransform,但这次有一个不同。这次我们创建一个XML文档,所以使用XMLWriter来代替以前的FileStream。下一个变化如下所示:

XsltArgumentList argBook=new XsltArgumentList();

BookUtils bu=new BookUtils();

argBook.AddExtensionObject("urn:ProCSharp",bu);

这段代码创建了XsltArgumentList对象。接着创建BookUtils对象的一个实例,在调用AddExtensionObject方法时,其参数是扩展的命名空间和要调用方法的对象。在调用Transform时,其参数是XsltArgumentList (argBook)、前面创建的XPathNavigatorXmlWriter对象。

下面是booksarg.xsl文档(基于books.xsl)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

                                  xmlns:bookUtil="urn:ProCSharp">

   <xsl:output method="xml" indent="yes"/>

  

   <xsl:template match="/">

      <xsl:element FTEL="books">

         <xsl:apply-templates/>

      </xsl:element> 

   </xsl:template>

   <xsl:template match="bookstore">

      <xsl:apply-templates select="book"/>

   </xsl:template>

   <xsl:template match="book">

      <xsl:element FTEL="discbook">

         <xsl:element FTEL="booktitle">

            <xsl:value-of select="title"/>

         </xsl:element>

         <xsl:element FTEL="showtext">

            <xsl:value-of select="bookUtil:ShowText()"/>

         </xsl:element>

      </xsl:element>  

   </xsl:template>

</xsl:stylesheet>

两行重要的代码已突出显示。首先,在给XsltArgumentList添加对象时,添加了前面创建的命名空间。然后,在调用方法时,使用标准的XSLT命名空间前缀语法。

另一种方式是使用XSLT脚本。可以在该样式表中包含C#VB JavaScript代码。最重要的是在Transform.Load调用中编译该脚本,这与目前的非.NET实现不同。这样就可以执行已经编译好的脚本,与ASP.NET的工作方式相同。

下面对前面的XSLT文件也进行这样的操作。首先给样式表添加脚本,在booksscript.xsl中进行的修改如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

                              xmlns:msxsl="urn:schemas-microsoft-com:xslt"

                              xmlns:user="http://wrox.com">

 

   <msxsl:script language="C#" implements-prefix="user">

  

      string ShowText()

         {

            return "This came from the ShowText method!";

         }

   </msxsl:script>

   <xsl:output method="xml" indent="yes"/>

      <xsl:template match="/">

   <xsl:element FTEL="books">

      <xsl:apply-templates/>

   </xsl:element> 

      </xsl:template>

   <xsl:template match="bookstore">

      <xsl:apply-templates select="book"/>

   </xsl:template>

      <xsl:template match="book">

      <xsl:element FTEL="discbook">

      <xsl:element FTEL="booktitle">

         <xsl:value-of select="title"/>

      </xsl:element>

      <xsl:element FTEL="showtext">

        <xsl:value-of select="user:ShowText()"/>

      </xsl:element>

    </xsl:element>  

   </xsl:template>

</xsl:stylesheet>

其中的改变已突出显示。设置脚本的命名空间,添加代码(可以从VS.NET IDE中复制和粘贴),在样式表上执行调用。输出结果与前面示例的相同。

总之,在进行转换时,一定要记住使用正确的XML数据存储:如果不需要编辑功能,就使用XPathDocument;如果要从ADO.NET中获得数据,就使用XmlDataDocument;如果需要编辑数据,就使用XmlDocument。其他过程都相同。

更多DotNet好文章www.zdexe.com

赞助商链接

热门内容

相关内容

联系我们

联系方式