Использование C# кода и объектов расширения (extension objects) в XSLT-процессоре .NET Framework

В .NET реализована спецификация XSLT 1.0 и его возможностей за частую не хватает. Например, отсутствует использование регулярных выражений, нет кодирования строк для использования в URL и т. д. В то же время .NET Framework позволяет обойти ограничения за счет таких средств как:
  1. параметры XSL трансформации;
  2. встраивание кода на JavaScript, VB.NET, C# и других языках;
  3. использование объектов расширения (extension objects.

В этой статье я хочу остановиться только на 2-х способах, которые сам регулярно использую, внедрение кода на С# и объекты расширения. Чтобы примеры были более конкретными, допустим, что у нас есть XML файл в котором содержатся данные для формирования линки на поиск в Bing. Вот пример такого XML файла:

Чтобы примеры были более конкретными, допустим, что у нас есть XML файл в котором содержатся данные для формирования линки на поиск в Bing.

Вот пример такого XML файла:

    xml version="1.0" encoding="utf-8" ?>

    <queries>

    <query title="A & B" term="A & B"/>

    queries>

Если в такого рода задаче не кодировать параметры для URL, то специальные символы (как &) не будут закодированы и URL будет распознан не верно либо может сформироваться невалидный URL.
Ниже приведен пример поиска по запросу из XML файла без кодирования параметров

    clip_image002

А здесь правильный вариант

    clip_image004

В первом случае символ & не был закодирован и не распознан, как часть строки поиска. Во втором случае & был закодирован и Bing распознал его.

Ниже приведены примеры, как можно добавить кодировние URL внедрением C# кода и с использованием объектов расширения. Фрагменты C# кода и XSLT на которые надо обратить внимание, выделены жирным и увеличенным шрифтом.

Пример XSLT с внедрением С# кода

    xml version="1.0" encoding="utf-8"?>

    <xsl:stylesheet

    version="1.0"

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

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

    xmlns:utility="urn:utility-scripts"

    exclude-result-prefixes="msxsl">

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

    <xsl:template match="query">

    <xsl:element name="a">

    <xsl:attribute name="href">

    <xsl:value-of select="concat('http://bing.com/search?q=', utility:EncodeUrl(@term))"/>

    xsl:attribute>

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

    xsl:element>

    <br />

    xsl:template>

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

    <msxsl:assembly name="system.web" />

    public string EncodeUrl(string rawUrl) {

    return System.Web.HttpUtility.UrlEncode(rawUrl);

    }

    ]]>

    msxsl:script>

    xsl:stylesheet>

Пример с использованием объектов расширения
XSLT:

    xml version="1.0" encoding="utf-8"?>

    <xsl:stylesheet

    version="1.0"

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

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

    xmlns:utility="urn:utility-scripts"

    exclude-result-prefixes="msxsl">

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

    <xsl:template match="query">

    <xsl:element name="a">

    <xsl:attribute name="href">

    <xsl:value-of select="concat('http://bing.com/search?q=', utility:EncodeUrl(@term))"/>

    xsl:attribute>

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

    xsl:element>

    <br />

    xsl:template>

    xsl:stylesheet>

Вызывающий C# код:

    class Program

    {

    static void Main(string[] args)

    {

    XslCompiledTransform xsltAndExtObjTransform = new XslCompiledTransform();

    xsltAndExtObjTransform.Load("..\\..\\XsltAndExtObj.xslt");

    XsltArgumentList arguments = new XsltArgumentList();

    arguments.AddExtensionObject("urn:utility-scripts", new Program());

    using (StreamWriter writer = File.CreateText("XsltAndExtObj.html"))

    {

    xsltAndExtObjTransform.Transform("..\\..\\Data.xml", arguments, writer);

    }

    }

    public string EncodeUrl(string rawUrl)

    {

    return System.Web.HttpUtility.UrlEncode(rawUrl);

    }

    }


Заключение
Описанные методы дают огромные возможности для расширения возможностей XSLT, но нужно помнить, что есть и плата – это потеря некоторой переносимости кода. Такой XSLT не возможно без переработки использовать в среде отличной от .NET – таких как Java или PHP и т. д.

Если же сравнивать межу собой внедрение c# кода и объекты расширения, то предпочтительней использовать объекты расширения. Их проще разрабатывать – есть подсветка синтаксиса и синтаксические ошибки выявляются на этапе компиляции проекта . Проще сопровождать – можно (и нужно) написать unit-test для проверки логических ошибок. Ну и на конец объект расширения можно будет использовать повторно (и не только в XSLT).

Удобство в использовании объектов расширения в том, что весь код, необходимый для их работы находится в том же XSLT файле. Без каких либо дополнительных усилий и зависимостей, XSLT c объектами расширения можно использовать в другой трансформации, другом .NET проекте.

В завершение статьи, тем кого заинтересовала данная тема хочу посоветовать посмотреть соответствующий раздел MSDN, где достаточно подробно описаны возможности расширения XSLT.

Комментарии

Популярные сообщения из этого блога

Как узнать, кто заблокировал файл или папку

Команды docker save/load, docker export/import – в чем отличие, как и когда ими пользоваться

Виртуальная машина QEMU с Linux (Ubuntu) на Windows 10