在XSLT中共享样式表

时间:2009-03-14 22:42:26

标签: xslt

我想在XSLT中创建一个主模板,它可以存储在一个单独的文件中。每个其他页面样式表都使用xsl:import共享它。

master.xslt     

 <xsl:template match="Page">
  <html>
   <head>
   </head>
   <body>

     <call-template name="Content"/>

   </body>
  </html> 
 </xsl:template>
<xsl:stylesheet>

page.xslt

<xsl:stylesheet>
<xsl:import href="master.xslt"/>

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

<xsl:template name="Content">
  ... apply something page-specific
</xsl:template>

</xsl:stylesheet>

page.xml

<Page>
 ... something page-specific
</Page>

我能改进这个解决方案吗?

  • 我无法从主样式表开始,因为我将需要xsl:import everything。
  • 我不希望master.xslt包含每个特定页面的引用。

另一个决定(反对xslt精神)可能是这样的:

master.xslt     

<xsl:template name="masterHead">
 <html>
  <head>
  </head>
  <body>
</xsl:template>

<xsl:template name=masterEnd>
 </body>
 </html> 
</xsl:template>

</xsl:stylesheet>

page.xslt

<xsl:stylesheet>
<xsl:import href="master.xslt"/>

<xsl:template match="/">
  <call-template name=masterHead>
   ... apply something page-specific
  <call-template name=masterEnd/>
</xsl:template>

</xsl:stylesheet>

我们不需要任何通用的根<Page>元素。

3 个答案:

答案 0 :(得分:1)

使用<xsl:import>是正确的设计决策。这正是XSLT指令的主要用例。

可以更进一步 - 查找<xsl:apply-imports>指令,以及导入的样式表如何应用模板,其中的操作和含义绝对不知道任何东西。后者称为Higher-Order-Functions,在XSLT中使用FXSL library实现(完全用XSLT编写)。

答案 1 :(得分:0)

这看起来对我来说是正确的...过去我曾经使用的很常见(尽管我经常使用<xsl:include/>,但要么应该工作)。我可能做的主要改变是使匹配更明确(至少在master xslt中) - 即

<xsl:template match="/Page"> <!-- leading slash -->

所以它不会意外匹配其他位置的Page元素(例如,数据分页,如<Page Index="3" Size="20"/>)。

我做的另一件常见的事情是添加“*”匹配,如果我没有针对某个节点的更具体的匹配,则使用xsl:message来引发错误。当你有错字等时,这会更加明显。

答案 2 :(得分:0)

我很高兴找到这个例子,因为我一直在寻找验证,这实际上是主/从模板设置的正确方法。 然而,提供的示例在tomcat上没有开箱即用 - 所以只是为了帮助那些只知道如何复制粘贴的人,这是一个有效的tomcat主/从文件集。

Master.xsl:

<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" encoding="iso-8859-15" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" indent="no"/>
<!-- http://stackoverflow.com/questions/646878/master-stylesheet-sharing-in-xslt -->
 <xsl:template match="ms247">
  <html>
   <head>
    <title>test</title>
   </head>

   <body>
    <div style="border: 1px solid black; width: 200px; float: left; margin: 10px; padding: 5px;">
     <xsl:call-template name="left"/>
    </div>
    <div style="border: 1px solid black; width: 200px; float: left; margin: 10px; padding: 5px;">
     <xsl:call-template name="content"/>
    </div>
    <div style="border: 1px solid black; width: 200px; float: left; margin: 10px; padding: 5px;">
     <xsl:call-template name="right"/>
    </div>
   </body>
  </html>
 </xsl:template>


 <xsl:template name="content">
  <span style="color: red">Content template is empty - overrule in page template.</span>
 </xsl:template>

 <xsl:template name="left">
  <span style="color: red">Left template is empty - overrule in page template.</span>
 </xsl:template>

 <xsl:template name="right">
  <span style="color: red">Right template is empty - overrule in page template.</span>
 </xsl:template>
</xsl:stylesheet>

和slave.xsl:

<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:import href="master.xsl"/>

 <xsl:template name="content">
  ... apply something page-specific
 </xsl:template>

 <xsl:template name="right">
  And we have RIGHT content!
  <!-- Execute matching template which is NOT triggered automatically -->
  <xsl:apply-templates select="params/param"/>
 </xsl:template>

 <!-- And we do not define any left template -->

 <!-- Example -->
 <xsl:template match="ms247/params/param">
  Paramters on page: <xsl:value-of select="@name"/><br/>
 </xsl:template>
</xsl:stylesheet>

希望这可以帮助别人 - 不要害羞地给我留言。