2010-09-09 4 views
5

Все,Применить XSLT Transform к уже преобразованному XML

У меня есть XML-файл, который я преобразовываю с помощью XSLT-документа в другой XML.

Могу ли я определить другой набор преобразований в том же XSLT-файле, который будет применяться в XML-результате первого преобразования?

Спасибо,

MK

+0

Вы хотите, чтобы две трансформации произошли за один проход? И если да, почему бы не вырезать среднего человека и просто трансформироваться непосредственно в ваш предполагаемый выход? – recursive

+0

Зачем вам это нужно с одним XSLT? Почему бы не создать два отдельных файла? –

+0

У меня есть приложение, которое принимает только один файл XSLT, но я хочу применить второе преобразование к вновь преобразованному файлу. – koumides

ответ

9

Да.

I. Это XSLT 1.0 Преобразование:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" 
xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vrtfPass1"> 
    <xsl:apply-templates/> 
</xsl:variable> 

<xsl:template match="node()|@*" name="identity"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="node()|@*" mode="pass2"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*" mode="pass2"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="num/text()"> 
    <xsl:value-of select="2*."/> 
</xsl:template> 

<xsl:template match="num/text()" mode="pass2"> 
    <xsl:value-of select="1+."/> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:apply-templates select="ext:node-set($vrtfPass1)/*" mode="pass2"/> 
</xsl:template> 
</xsl:stylesheet> 

при нанесении на этом XML-документ:

<t> 
<num>1</num> 
<num>2</num> 
<num>3</num> 
<num>4</num> 
<num>5</num> 
</t> 

производит:

<t> 
    <num>3</num> 
    <num>5</num> 
    <num>7</num> 
    <num>9</num> 
    <num>11</num> 
</t> 

Обратите внимание:

  1. Два преобразования фактически выполняются, второй осуществляется по результатам первого.

  2. Результатом первого преобразования является содержание переменной $vrtfPass1.

  3. В XSLT 1.0 типа переменных, которые содержат динамически (временный) XML-дерево (XML-документ или фрагмент XML) является RTF (Результат-дерево-фрагмент). В RTF нет операций XPath - его необходимо преобразовать в обычный набор узлов, используя функцию расширения xxx:node-set(), которая предоставляется подавляющим большинством поставщиков процессоров XSLT 1.0. В этом примере используется exslt: node-set(), поскольку EXSLT реализуется многими разными поставщиками.

  4. Второе преобразование применяется к результату первого: <xsl:apply-templates select="ext:node-set($vrtfPass1)/*" mode="pass2"/>. Для четкого разделения кода двух преобразований используется отдельный mode.

  5. Первое преобразование умножает каждые num/text() на 2. Второе преобразование увеличивает каждый num/text(). В результате 2*.+1

II. Это XSLT 2.0 Преобразование:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" > 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vPass1"> 
    <xsl:apply-templates mode="pass1"/> 
</xsl:variable> 

<xsl:template match="node()|@*" mode="pass1"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*" mode="pass1"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="node()|@*" mode="pass2"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*" mode="pass2"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="num/text()" mode="pass1"> 
    <xsl:value-of select="2*xs:integer(.)"/> 
</xsl:template> 

<xsl:template match="num/text()" mode="pass2"> 
    <xsl:value-of select="1+."/> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:apply-templates select="$vPass1" mode="pass2"/> 
</xsl:template> 
</xsl:stylesheet> 

при нанесении на том же самом документе XML, производит тот же самый разыскиваемого и правильный результат.

Замечание: В XSLT 2.0/XPath 2.0 тип RTF был отменен. Нет необходимости использовать функцию расширения xxx:node-set().

+0

+1 Хороший ответ. Это показывает, почему RTF был плохой выбор дизайна из WG ... Кроме того, разве нам не нужно показывать использование функции «fn: function-available» при использовании функций расширения? – 2010-09-09 20:05:17

+0

@Alejandro: Возможно, использование функции 'fn: function-available' было бы полезно для определения того, какая из многих расширений xxx: node-set() расширяет XSLT-процессор, но это обычно известно. –

+0

Отлично. Большое спасибо Dimitre. – koumides

Смежные вопросы