在XSL中:如何避免选择块用于包装元素?

时间:2011-08-26 07:35:40

标签: xml xslt

有一种情况经常出现。我正在解析XML并通过XSLT 1.0生成我的XHTML文档。

案例:

/* XML */
<Image src="path-to-img.jpg" href="link-to-page.html" />

/* XSL */
<xsl:choose>
    <xsl:when test="@href">
    <a href="{@href}">
       <img src="{@src}"/>
    </a>
</xsl:when>
<xsl:otherwise>
    <img src="{@src}"/>
</xsl:otherwise>
</xsl:choose>

你看到了问题:如果有一个href设置,我只是提取案例。我对这种方法不满意,但我没有看到实现这一点的另一种选择。

有什么想法吗?

3 个答案:

答案 0 :(得分:7)

在模板中消除显式条件指令的方法是在模板的匹配模式中使用模式匹配

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="Image[@href]">
    <a href="{@href}">
     <xsl:call-template name="basicImage" />
    </a>
 </xsl:template>

 <xsl:template match="Image" name="basicImage">
   <img src="{@src}"/>
 </xsl:template>
</xsl:stylesheet>

XSLT 2.0:使用 <xsl:next-match> 有一个特别优雅的解决方案:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="Image[@href]">
    <a href="{@href}">
    <xsl:next-match/>
    </a>
 </xsl:template>

 <xsl:template match="Image" name="basicImage">
   <img src="{@src}"/>
 </xsl:template>
</xsl:stylesheet>

两种转换,应用于提供的XML文档

<Image src="path-to-img.jpg" href="link-to-page.html" />

生成想要的正确结果

<a href="link-to-page.html">
   <img src="path-to-img.jpg"/>
</a>

答案 1 :(得分:2)

选项#1您可以创建非条件a和图像以及使用xsl:if追加属性(注意在这种情况下有一些缺点 - 始终存在标记a但没有href - 对于最终用户来说这不是问题):

<a>
   <xsl:if test="@href">
      <xsl:attribute name="href" value="{@href}"/>
   </xsl:if>
   <img src="{@src}"/>

</a>

选项#2如果javascript适用 - 只需放置img处理onclick

答案 2 :(得分:2)

为避免重复代码,您可以使用命名模板来包含用于呈现 img 标记的代码

<xsl:template name="img">
   <img src="{@src}" />
</xsl:template>

然后您可以这样称呼它

<xsl:call-template name="img" />

因此,完成的XSLT将是

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

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/Image ">
      <xsl:choose>
         <xsl:when test="@href">
            <a href="{@href}">
               <xsl:call-template name="img" />
            </a>
         </xsl:when>
         <xsl:otherwise>
            <xsl:call-template name="img" />
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>

   <xsl:template name="img">
      <img src="{@src}" />
   </xsl:template>
</xsl:stylesheet>

虽然您仍然有两个 xsl:call-template 命令,但现在只需在一个地方完成对 img 标记呈现的任何更改。您也可以在XSLT中的任何位置调用此模板,假设当前节点是图像节点。