java - 对同一个 XSL 样式表使用不同的 HTML 模板

标签 java html xslt velocity xalan

是否可以对同一个 XSLT 样式表使用不同的 HTML 布局?

我一直在阅读 XSLT,我看到的大多数示例表明 HTML 代码实际上嵌入在样式表中。

是否可以对多个 HTML 布局使用相同的样式表? (我的想法类似于 Velocity 的工作方式——即可以使用相同的 Velocity 标签处理多个 HTML 文件)。

我正在使用 Java Xalan 处理器来处理 XSLT。

编辑

我已经尝试了下面的@Dimitre Novatchev 方法,并且效果很好。 唯一的问题是我将如何处理元素循环?比如xml文档修改为:

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

如何遍历每个年龄元素?

这是我在 HTML 模板上尝试的内容,但我没有看到任何区别:

<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>

预期输出

我希望上面的输出是

Hi JohnSmith!
You are 25 years old. 

25, 33, 55

最佳答案

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

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

骨架 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”中:转换生成”)。这些将由 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>

关于java - 对同一个 XSL 样式表使用不同的 HTML 模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13377939/

相关文章:

xml - 使用模板匹配测试节点是否为空或包含 NULL

java - Hibernate 和 jOOQ 共享事务

java - org.hibernate.AssertionFailure : collection was processed twice by flush()

html - Flexbox 作为 Firefox 和 Opera 上表格的替代品

javascript - 无法在 Angular ui.router 中的子状态之间切换

javascript - 为什么不在网页内容中使用iframe的充分理由

xslt - 如何识别 XSLT 输入或 XPath 中的行号?

java - 将 JSON 数据解析到 listView 中

java - 我可以使用 Spring Security @PreAuthorize 来检查 HTTP header 吗?

xslt - XSL 格式数字不四舍五入