3

Is it possible to use a different HTML layout for the same XSLT stylesheet?

I have been reading up on XSLT and most examples i see show that the HTML code is actually embedded within the stylesheet.

Is it possible to use the same stylesheet for more than one HTML layout? (I am thinking similar to how Velocity works - i.e. multiple HTML files can be processed using the same Velocity tags).

I am using the Java Xalan processor to process the XSLT.

Edit

I have tried @Dimitre Novatchev approach below and it works perfectly. The only thing is how would i handle looping through elements? For example, if the xml document is modified to be:

<person>
 <fname>John</fname>
 <lname>Smith</lname>
 <age>25</age>
 <age>33</age>
 <age>55</age>
</person>

How can i iterate through each of the age elements?

Here is what i tried on the HTML template but i didnt see any difference:

<html xmlns:gen="my:tranform-generated">
 <body>
  <h1>Hi <gen:fname/> <gen:lname/>!</h1>

  You are <gen:age/> years old.  

  <gen:for-each select="/person/age">
    <gen:age/>,
  </gen:for-each>

 </body>
</html>

Expected output

I would like the output of the above to be

Hi JohnSmith!
You are 25 years old. 

25, 33, 55
4

2 回答 2

6

是的,这是一个非常强大的技术,我称之为“填空”。

这是一个非常简短的示例:

骨架1:

<html xmlns:gen="my:tranform-generated">
 <body>
  <h1>Hi <gen:fname/>!</h1>
 </body>
</html>

骨架 2:

<html xmlns:gen="my:tranform-generated">
 <body>
  <h1>Hi <gen:fname/> <gen:lname/>!</h1>

  You are <gen:age/> years old.
 </body>
</html>

XSLT 转换作为外部参数传递“要使用的骨架”的 Uri,它“按原样”复制所有节点,但特殊命名的元素除外(其名称位于特殊命名空间“my:tranform-生成”)。这些被 XSLT 转换中与它们匹配的模板的结果替换。

以下是此类转换的示例

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:gen="my:tranform-generated" exclude-result-prefixes="gen">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pSkeleton" select="'file:///c:/temp/delete/Skeleton1.xml'"/>

 <xsl:variable name="vData" select="/"/>

 <xsl:template match="/">
  <xsl:apply-templates select="document($pSkeleton)/*"/>
 </xsl:template>

 <xsl:template match="*">
     <xsl:element name="{name()}">
       <xsl:copy-of select="namespace::*[not(. = 'my:tranform-generated')]"/>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:element>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>

 <xsl:template match="*[namespace-uri()='my:tranform-generated']">
  <xsl:value-of select="$vData/*/*[name() = local-name(current())]"/>
 </xsl:template>
</xsl:stylesheet>

当将此转换应用于此 XML 文档时

<person>
 <fname>John</fname>
 <lname>Smith</lname>
 <age>25</age>
</person>

产生了想要的正确结果(使用 Skeleton1.xml):

<html>
   <body>
      <h1>Hi John!</h1>
   </body>
</html>

当对同一个 XML 文档应用相同的转换,但$pSkeleton传递给它的外部参数的值为 时"file:///c:/temp/delete/Skeleton2.xml",我们再次得到想要的结果(格式化的 Skeleton2):

<html>
   <body>
      <h1>Hi JohnSmith!</h1>

      You are 25 years old.

   </body>
</html>

更新

这是一个如何处理迭代的示例——按照 OP 的要求:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:gen="my:tranform-generated" exclude-result-prefixes="gen">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pSkeleton" select="'file:///c:/temp/delete/Skeleton3.xml'"/>

 <xsl:variable name="vData" select="/"/>

 <xsl:template match="/">
  <xsl:apply-templates select="document($pSkeleton)/*"/>
 </xsl:template>

 <xsl:template match="*">
     <xsl:element name="{name()}">
       <xsl:copy-of select="namespace::*[not(. = 'my:tranform-generated')]"/>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:element>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>

 <xsl:template match="*[namespace-uri()='my:tranform-generated']">
  <xsl:value-of select="$vData/*/*[name() = local-name(current())]"/>
 </xsl:template>

 <xsl:template match="gen:context" priority="2">
     <xsl:apply-templates>
       <xsl:with-param name="pContext"
         select="$vData/*/*[name()=current()/@select][1]"/>
     </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="gen:iterate" priority="2">
  <xsl:param name="pContext"/>

  <xsl:variable name="vDelim" select="string(@delimiter)"/>

  <xsl:for-each select="$pContext/*[name()= current()/@select]">
   <xsl:if test="not(position()=1)"><xsl:copy-of select="$vDelim"/></xsl:if>
   <xsl:copy-of select="node()"/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Skeleton3.xml:

<html xmlns:gen="my:tranform-generated">
 <body>
  <h1>Hi <gen:fname/> <gen:lname/>!</h1>

  You are <gen:age/> years old.

  Education:
  <gen:context select="education">
    <gen:iterate select="degree" delimiter=", "/>
  </gen:context>
 </body>
</html>

当上述转换应用于此 XML 文档时:

<person>
 <fname>John</fname>
 <lname>Smith</lname>
 <age>25</age>

 <education>
  <degree>MSc. Biology</degree>
  <degree>MBa.</degree>
  <degree>PhD. Computer Science</degree>
 </education>
</person>

产生了想要的正确结果

<html>
   <body>
      <h1>Hi JohnSmith!</h1>

      You are 25 years old.

        Education:
        MSc. Biology, MBa., PhD. Computer Science
   </body>
</html>
于 2012-11-14T13:25:31.250 回答
0

是的,这是可能的。您可以在 xsl:if 标签中包围 html 块

例如:

<xsl:if test="value &gt; 75000"><p>Print out this html</p></xsl:if>
于 2012-11-14T11:34:42.863 回答