使用node-set()帮助多传递XSLT

时间:2009-09-28 22:27:42

标签: xslt

我需要以表格形式显示某些数据,并且更喜欢使用多遍 xslt使用node-set()以便我可以避免部署其他工具(如xsltproc)。 现在,我能够分两步完成所需的任务,即

步骤1:使用身份模板将XML-1转换为XMl-2(xsl:copy,使用xsl:element到 添加动态元素'dev'和'qa`):

<projectteam>
  <member>
    <name>John</name>
    <role>dev</role>
    <hrs>100</hrs>
  </member>
  <member>
    <name>Peter</name>
    <role>qa</role>
    <hrs>80</hrs>
  </member>
</projectteam>

<projectteam>
  <member>
    <name>John</name>
    <dev>100</dev>
  </member>
  <member>
    <name>Peter</name>
    <qa>80</qa>
  </member>
<projectteam>

然后,使用另一个XSLT-FO样式表将XML#2转换为具有所需布局的PDF文档:

name | dev | qa |
-----------------
John | 100 |    |
Peter|     | 80 |
-----------------
Total| 100 | 80 |

我尝试使用node-set()(我猜错了)将这两个步骤结合起来,但是 我得到的结果如下:

name | dev | qa |
-----------------
Total|  0  |  0 |

样式表-1:将XML-1转换为XML-2,导入另一个样式表'projDisplay.xsl', 使用node-set()来调用导入的样式表,但数据没有显示?

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  xmlns:exslt="http://exslt.org/common"
>

  <!-- import stylesheet to display XML-2 in tabular form -->
  <xsl:import href="projDisplay.xsl"/>

  <xsl:template match="/">
    <fo:root>
      <xsl:apply-templates/>
    </fo:root>
  </xsl:template>

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

    <!-- ==> This is where my problem is - it goes to the template defined in  -->
    <!-- projDisplay.xsl (xslt-fo, pretty big one with page layout etc. hence  -->
    <!-- not included here, but it works on its own though) as I can see the   -->
    <!-- table header, and an empty totals row, but non of the rows are displayed -->

    <xsl:apply-templates 
      select="exslt:node-set($newXmlData)/projectteam" mode="display"
    />
  </xsl:template>

  <!-- replace element 'role' with a new element - role name (i.e. dev or qa) -->
  <!-- and set its value as 'hrs                                              -->
  <xsl:template match="role">
    <xsl:element name="{.}"> <xsl:value-of select="../hrs"/> </xsl:element>
  </xsl:template>

  <!-- eliminate element 'hrs' -->
  <xsl:template match="hrs"/>
</xsl:stylesheet>

样式表中的注释部分对我来说不合适。有什么建议 关于如何纠正它?

谢谢!

2 个答案:

答案 0 :(得分:3)

这是有效的解决方案。它基于Tomalak的原始解决方案,有一些小问题 修改(如模式标志等)再次,感谢Tomalak !!

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exslt="http://exslt.org/common"
  version="1.0">

 <xsl:import href="projDisplay.xsl"/>

 <xsl:template match="/">
  <!-- store intermediate form as RTF -->
  <xsl:variable name="newXmlData">
   <xsl:apply-templates mode="filter"/>
  </xsl:variable>

  <!-- Now apply templates (with xslt-fo) defined in projDisplay.xsl with     -->
  <!-- the root template as <xsl:template match="projectteam" mode="display"> -->
  <!-- to the above RTF (i.e. after the original XML has be convertedr)       -->
  <xsl:apply-templates select="exslt:node-set($newXmlData)/projectteam" mode="display"/>

 </xsl:template>

 <!-- use identity templates to copy and modify original XML -->
 <xsl:template match="@*|node()" mode="filter">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()" mode="filter"/>
  </xsl:copy>
  </xsl:template>

 <!-- replace element 'role' with a new element - role name (i.e. dev or qa) -->
 <!-- and set its value as 'hrs                                              -->
 <xsl:template match="member/role" mode="filter">
  <xsl:element name="{.}"> <xsl:value-of select="../hrs"/> </xsl:element>
 </xsl:template>

 <!-- eliminate element 'hrs' -->
 <xsl:template match="hrs" mode="filter"/>

</xsl:stylesheet>

答案 1 :(得分:2)

怎么样:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  xmlns:exslt="http://exslt.org/common"
  exclude-result-prefixes="exslt"
>

  <xsl:import href="projDisplay.xsl"/>

  <xsl:template match="/">
    <!-- store intermediary format as a RTF -->
    <xsl:variable name="newXmlData">
      <xsl:apply-templates />
    </xsl:variable>
    <!-- now we can the apply imported rules -->
    <xsl:apply-templates 
      select="exslt:node-set($newXmlData)/projectteam"
      mode="import"
    />
  </xsl:template>

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

  <xsl:template match="member/role">
    <xsl:element name="{.}">
      <xsl:value-of select="../hrs" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="member/*" />

  <xsl:template match="projectteam" mode="import">
    <fo:root>
      <xsl:apply-imports />
    </fo:root>
  </xsl:template>

</xsl:stylesheet>