2011-12-17 5 views
4

Можно ли применить шаблон к результату шаблона вызова?XSLT - применить шаблон к результату шаблона вызова

Например, xml и 2 xslt ниже.

index.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <book> 
    <title>Ethics</title> 
    </book> 
    <book> 
    <title>Beyond Good and Evil</title> 
    </book> 
</root> 

index2.xsl

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:template match="/" name="temp2"> 
    <foo> 
    <xsl:for-each select="//book"> 
     <bar><xsl:value-of select="."/></bar> 
    </xsl:for-each> 
    </foo> 
    </xsl:template> 
</xsl:stylesheet> 

и index.xsl звонит index2.xsl

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
<xsl:include href="index2.xsl" /> 
<!-- apply a template to the <xsl:call-template name="temp2" /> result --> 
</xsl:stylesheet> 

Есть ли способ, чтобы применить шаблон к результат <xsl:call-template name="temp2" /> в index.xsl?

Заранее благодарен.

ответ

8

Есть ли способ применить шаблон к результату <xsl:call-template name="temp2" /> в index.xsl?

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

Вот полный пример обработки многопроходной (я использую xsl:apply-templates и не xsl:call-template, но вы можете свободно модифицировать этот пример, чтобы использовать именованные шаблоны и xsl:call-template вместо):

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

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

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

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

<xsl:template match="num" mode="pass2"> 
    <num><xsl:value-of select=". * ."/></num> 
</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 элементов удваивается в первом проходе, а затем квадрат во втором проходе) производится:

<num>4</num> 
<num>16</num> 
<num>36</num> 
<num>64</num> 
<num>100</num> 
<num>144</num> 
<num>196</num> 
<num>256</num> 
<num>324</num> 
<num>400</num> 

II. В XSLT 2,0

«Тип» в формате RTF был отменен, так что это гораздо проще, чтобы указать обработку многоходовой, которая становится почти неотличимы от функционального состава, как показан в следующем эквивалентном преобразовании показывает:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my" exclude-result-prefixes="my"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/*"> 
    <xsl:sequence select="my:squareAll(my:doubleAll(*))"/> 
</xsl:template> 

<xsl:function name="my:doubleAll" as="element()*"> 
    <xsl:param name="pElems" as="element()*"/> 

    <xsl:for-each select="$pElems"> 
    <xsl:copy> 
    <xsl:sequence select=". + ."/> 
    </xsl:copy> 
    </xsl:for-each> 
</xsl:function> 

<xsl:function name="my:squareAll" as="element()*"> 
    <xsl:param name="pElems" as="element()*"/> 

    <xsl:for-each select="$pElems"> 
    <xsl:copy> 
    <xsl:sequence select=". * ."/> 
    </xsl:copy> 
    </xsl:for-each> 
</xsl:function> 
</xsl:stylesheet> 

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

<num>4</num> 
<num>16</num> 
<num>36</num> 
<num>64</num> 
<num>100</num> 
<num>144</num> 
<num>196</num> 
<num>256</num> 
<num>324</num> 
<num>400</num> 
+0

Очень гр леск и подробное объяснение, Большое спасибо! – Eric

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