2010-12-31 4 views
9

У меня возникла ситуация, когда мне кажется, что мне нужно создать цепочку преобразования xslt (т. Е. Выход одного преобразования xslt, вводимого в другой). Первое преобразование довольно сложно с множеством xsl: choice и xpaths предков. Моя мысль состоит в том, чтобы преобразовать xml в xml, который затем может быть легко преобразован в html.Является ли daisy chaining xslt принятой практикой?

Мой вопрос: «Является ли эта стандартная практика, или я что-то не хватает?»

Заранее спасибо.

Стивен

+0

Хороший вопрос, +1. См. Мой ответ для объяснения и полный пример кода. :) –

+1

Да, это принято, но не всегда необходимо. Если вы используете Java, Transformerfactory может быть настроен на последовательные преобразования подбородка и избегать ненужных операций синтаксического анализа. http://stackoverflow.com/questions/1312406/efficient-xslt-pipeline-in-java-or-redirecting-results-to-sources/1319774#1319774 –

ответ

0

Я не думаю, что это был стандарт практика, в частности, так как вы можете преобразовать один XML-диалект непосредственно к другому.

Однако, если обработка сложна, разделение ее на несколько этапов (применение другого преобразования на каждом шаге) действительно упрощает каждый шаг и имеет смысл.

Это действительно зависит от конкретной ситуации.

9

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

Вот пример (слишком просто, чтобы быть значимым, но иллюстрирующий полностью, как это делается):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:variable name="vrtfPass1"> 
    <xsl:apply-templates select="/*/*"/> 
    </xsl:variable> 

    <xsl:variable name="vPass1" 
     select="ext:node-set($vrtfPass1)"/> 

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

<xsl:template match="num[. mod 2 = 1]"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

<xsl:template match="num" mode="pass2"> 
    <xsl:copy> 
    <xsl:value-of select=". *2"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

когда это преобразование применяется на следующий документ XML:

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 

Требуется, правильный результат:

<num>2</num> 
<num>6</num> 
<num>10</num> 
<num>14</num> 
<num>18</num> 

Объяснение:

  1. На первом этапе XML-документ преобразуется и результат определяется как значение переменной $vrtfPass1. Это копирует только элементы num, которые имеют нечетное значение (даже не).

  2. $vrtfPass1 переменных, будучи тип RTF, не может непосредственно использоваться для XPath-выражения поэтому мы преобразуем его в нормальное дерево, используя EXSLT (реализованное большинство XSLT 1.0 процессоров) функции ext:node-set и определяющего другие переменным - - $vPass1, значение которого - это дерево.

  3. теперь выполнить второе преобразование в нашей цепочке превращений - на результате первого преобразования, которая сохраняется как значение переменной $vPass1. Чтобы не путаться с шаблоном первого прохода, мы указываем, что новая обработка должна быть в именованном режиме, называемом «pass2». В этом режиме значение любого элемента num умножается на два.

XSLT 2.0 решение (без RTFS):

<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:template match="/"> 
    <xsl:variable name="vPass1" > 
    <xsl:apply-templates select="/*/*"/> 
    </xsl:variable> 
    <xsl:apply-templates mode="pass2" 
     select="$vPass1/*"/> 
</xsl:template> 

<xsl:template match="num[. mod 2 = 1]"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

<xsl:template match="num" mode="pass2"> 
    <xsl:copy> 
    <xsl:value-of select=". *2"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 
1

Если это ваша ситуация (или может стать вашей ситуации):

  1. преобразование начальной XML в mediary XML.
  2. Возможно преобразование медиатора xml в final1_html.
  3. Возможно преобразование медиатора xml в final2_html (совсем не похоже на final1_html).

или

  1. Transform начальный XML в mediary XML. Вероятно, это со временем изменится.
  2. Преобразование медиатора xml в final_html. Это вряд ли изменится с течением времени.

Тогда имеет смысл использовать двухэтапное преобразование.

Если это ваша ситуация:

  1. преобразование начальной XML в mediary XML.
  2. Преобразование медиатора xml в final_html.

Тогда рассмотрите не два степпинга. Вместо этого просто выполните одно преобразование.

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