将XSLT Transform应用于已转换的XML

时间:2010-09-09 16:03:54

标签: xslt

全部,

我有一个XML文件,我使用XSLT文档将其转换为另一个XML。

我可以在同一个XSLT文件中定义另一组转换,以便在第一次转换的结果XML中应用吗?

谢谢,

MK

1 个答案:

答案 0 :(得分:9)

<强>予。这个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

  6. <强> 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()扩展功能。