transForm.Transform(nav, argBook, xw);
xw.Close();
}
// простой тестовый класс
public class BookUtils {
public BookUtils() {}
public string ShowText() {
return 'This came from the ShowText method!';
}
}
Вывод преобразования (argSample.xml
) выглядит так:
<?xml version='1.0'?>
<books>
<discbook>
<booktitle>The Autobiography of Benjamin Franklin</booktitle>
<showtext>This came from the ShowText method!</showLext>
</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
) вместе с XPathNavigator
и созданный объект XmlWriter
. Вот документ booksarg.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 name='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 name='discbook'>
<xsl:element name='booktitle'>
<xsl:value-of select='title'/>
</xsl:element>
<xsl:element name='showtext'>
<xsl:value-of select='bookUtil:ShowText()'/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Здесь имеются две важные строки. В начале добавляется пространство имен, которое создается при добавлении объекта к XsltArgumentList
. Затем применяется стандартный синтаксис использования префикса перед пространством имен XSLT и вызывается метод.
Иначе это можно было бы выполнить с помощью сценария XSLT. В таблицу стилей можно включить код C#, VB и JavaScript. Большим достоинством этого является то, что в отличие от текущих реализаций, сценарий компилируется при вызове Transform.Load
; таким образом выполняются уже откомпилированные сценарии, в значительной степени так же, как работает ASP.NET. Давайте выполним предыдущий пример таким способом. Добавим сценарий к таблице стилей. Эти изменения можно увидеть в файле bookscript.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 name='books'>
<xsl:apply-templates/>
</xsl:element>