在选择建筑中包装元素。如何提高?

时间:2010-05-18 09:49:13

标签: xslt optimization

有没有办法优化此代码。

<xsl:choose>
    <xsl:when test="val1 = val2">
        <xsl:apply-templates select="node"/>
    </xsl:when>
    <xsl:otherwise>
        <div>
            <xsl:apply-templates select="node"/>
        </div>
    </xsl:otherwise>
</xsl:choose>

我不喜欢写两次相同的<xsl:apply-templates select="node"/>


更新

这个想法是根据比较的结果来做两件事的一个

  1. 只需打印一些信息(我们在应用模板<xsl:apply-templates select="node"/>后获得)。

  2. 打印相同的信息,但事先在容器中“打包”(例如div)。

    < / LI>

3 个答案:

答案 0 :(得分:0)

使用

<xsl:apply-templates select="node">
  <xsl:sort select="not(val1 = val2)"/>
</xsl:apply-templates>

这是一个完整的例子。这种转变:

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

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

 <xsl:template match="/*">
  <t>
        <xsl:apply-templates select="node">
          <xsl:sort select="not(val1 = val2)"/>
        </xsl:apply-templates>
  </t>
 </xsl:template>

 <xsl:template match="node[not(val1 = val2)]">
  <div>
     <node>
       <xsl:apply-templates/>
     </node>
  </div>
 </xsl:template>
</xsl:stylesheet>

应用于此XML文档时

<t>
  <node>
    <val1>1</val1>
    <val2>2</val2>
  </node>
  <node>
    <val1>3</val1>
    <val2>3</val2>
  </node>
</t>

产生想要的正确结果:

<t>
   <node>
      <val1>3</val1>
      <val2>3</val2>
   </node>
   <div>
      <node>
         <val1>1</val1>
         <val2>2</val2>
      </node>
   </div>
</t>

解决方案说明

每当<xsl:apply-templates>有一个<xsl:sort>子项时,所选的节点将根据<xsl:sort>子项(ren)中提供的数据进行排序,并在每个选定的项目上应用模板的结果节点以该(排序)顺序出现在输出中 - 而不是按文档顺序。

在上面的转型中我们有:

<xsl:apply-templates select="node"> 
  <xsl:sort select="not(val1 = val2)"/> 
</xsl:apply-templates> 

这意味着将模板应用于名为node的元素的结果,val1=val2将在将模板应用于名为node的元素的结果之前出现val1=val2不是真的。这是因为falsetrue之前排序。

如果此说明不明确,请读者阅读有关<xsl:sort>的更多信息。

答案 1 :(得分:0)

这个简单的例子很难实现,但如果包装代码和重复代码的数量值得打扰,你有两个选择:

  1. 引入一系列具有不同模式的模板:

    <!-- instead of choose -->
    <xsl:apply-template match="." mode="container" />
    ...
    <xsl:template match="container" mode="container">
        <xsl:apply-templates select="." mode="dup-group"/>
    </xsl:template>
    
    <xsl:template match="container[val1=val2]" mode="container">
        <div>
            <xsl:apply-templates select="." mode="dup-group"/>
        </div>
    </xsl:template>
    
    <xsl:template match="container" mode="dup-group">
        <xsl:apply-templates select="node"/>
        <!-- other duplicate code -->
        ...
    </xsl:template>
    
  2. 将部分代码移动到单独的导入样式表中,并覆盖当前样式表中的模板规则:

    <xsl:template match="container[val1=val2]">
        <div>
            <xsl:apply-imports />
        </div>
    </xsl:template>
    

答案 2 :(得分:-1)

您在此处发布的xslt不是很优化。如果您不想复制的代码超过两行,则可以通过创建命名模板并调用它来进行优化。在这个例子中,它确实没有多大意义,但你会明白这个想法:

<xsl:when test="val1=val2">
  <xsl:call-template name="optimized"/>
</xsl:when>
<xsl:otherwise>
  <div>
    <xsl:call-template name="optimized"/>
  </div>
</xsl:otherwise>

模板:

<xsl:template name="optimized">
  <xsl:apply-templates select="node"/>
</xsl:template>

被调用的模板与调用代码位于相同的上下文中,因此您只需将不想复制的代码复制到命名模板即可。