【问题标题】:Extend attrbiute instead of setting it?扩展属性而不是设置它?
【发布时间】:2014-08-05 09:56:01
【问题描述】:

我正在构建一个相当复杂的 XSLT 以生成一些 HTML 标记。

我的目标之一是使用一些模板“扩展”生成的标记的class 属性。

不幸的是,它不起作用,因为 XSLT 标记 <xsl:attribute> 只能“设置”属性。不要操纵现有的。

当我尝试时,原始属性被擦除。

这是一个小复制:

XML:

<node>
    <item value="1" type="abc"/>
    <item value="20" type="zxy"/>
</node>

XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="utf-8" indent="no"/>
  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>
  <xsl:template match="/node/item">
    <p class="{@type}">
      <xsl:call-template name='rule1' />
      <xsl:call-template name='rule2' />
    </p>
  </xsl:template>
  <xsl:template name='rule1'>
    <xsl:attribute name='class'>
      <xsl:choose>
        <xsl:when test="@value mod 2 = 0">alpha</xsl:when>
        <xsl:otherwise>omega</xsl:otherwise>
      </xsl:choose>
    </xsl:attribute>
  </xsl:template>
  <xsl:template name='rule2'>
    <xsl:attribute name='class'>
      <xsl:choose>
        <xsl:when test="@value mod 10 = 0">beta</xsl:when>
        <xsl:otherwise>gamma</xsl:otherwise>
      </xsl:choose>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>                       

我想输出:

<?xml version="1.0" encoding="utf-8"?>
<p class="abc omega"/>
<p class="zxy beta alpha"/>

但它输出

<?xml version="1.0" encoding="utf-8"?>
<p class="omega"/>
<p class="beta"/>

是否可以保留原始属性,或者在实用程序模板中检索它以重新使用它?

【问题讨论】:

  • 你不能设置一个 xsl:variable 以便以后重用它吗? (例如将@type 设置为变量,然后将新属性设置为“concat(variablename, appends)?我对 xslt 还不是很满意,但我认为这会起作用。
  • xslt 中的一个变量不能设置多次。这在我上面的 sn-p 中并不明显,但我将链接模板以检查多个业务规则并将多个类应用于我的节点。如果我使用变量,我仍然必须在每个模板调用中声明至少一个变量。
  • 我已更新我的 sn-p 以包含多个模板
  • 它不能动态更新,但每次在xml中找到与该模板匹配的节点时,每次调用模板时都可以重新填充它。
  • 事实上你不能像 &lt;xsl:value-of select="concat(@type, ' appends')"/&gt; 那样做,@type(或者如果你更深入的话,是父节点的 XPath)仍然是他们以前的内容吗?

标签: xslt


【解决方案1】:

似乎这个答案只能满足一个深度的、非重复的类。 在您调用的模板的开头包含此内容:

<xsl:variable name="type" select="@type"/>

然后在更新属性值的时候,试试:

<xsl:attribute select="class">
    <xsl:choose>
        <xsl:when test="@value mod 2 = 0">
            <xsl:value-of select="concat($type, ' alpha')"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="concat($type, ' omega')"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:attribute>

再说一次,我对 XSLT 不是很满意,但我最近在测试中尝试了类似的东西,它很有魅力。希望对您有所帮助。

编辑:我不确定,但您可能必须在 concat 函数中放置“空格”的转义值,我忘记了。

【讨论】:

    【解决方案2】:

    一个可行的解决方案可能是(感谢@aleski 的建议)

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" encoding="utf-8" indent="no"/>
      <xsl:template match="/">
        <xsl:apply-templates />
      </xsl:template>
      <xsl:template match="/node/item">
        <p>
        <xsl:attribute name='class'>
          <xsl:value-of select="@type" />
          <xsl:call-template name='rule1' />
          <xsl:call-template name='rule2' />
        </xsl:attribute>
        </p>
      </xsl:template>
      <xsl:template name='rule1'>
          <xsl:choose>
            <xsl:when test="@value mod 2 = 0"><xsl:value-of select="' alpha'" /></xsl:when>
            <xsl:otherwise><xsl:value-of select="' omega'" /></xsl:otherwise>
          </xsl:choose>
      </xsl:template>
      <xsl:template name='rule2'>
    
          <xsl:choose>
            <xsl:when test="@value mod 10 = 0"><xsl:value-of select="' beta'" /></xsl:when>
            <xsl:otherwise><xsl:value-of select="' gamma'" /></xsl:otherwise>
          </xsl:choose>
    
      </xsl:template>
    </xsl:stylesheet>   
    

    【讨论】:

      【解决方案3】:

      您喜欢晦涩难懂的编码解决方案吗?如果是这样,您可以这样重写您的解决方案:

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" encoding="utf-8" indent="no"/>
      
        <xsl:template match="/node/item">
          <p class="{@type} {substring('alphaomega', 1 + 5 * (@value mod 2 = 0), 5)} {normalize-space(substring('beta gamma', 1 + 5 * (@value mod 10 = 0), 5))}">
          </p>
        </xsl:template>
      </xsl:stylesheet>    
      

      因此,在一个属性中包含三个属性值模板。如果你看看其中一个......

      {substring('alphaomega', 1 + 5 * (@value mod 10 = 0), 5)} 
      

      这利用了这样一个事实,即“true”在数值表达式中的计算结果为 1,而“false”的计算结果为 0。因此,当表达式为真时,返回字符串的前五个字符。为假时,后五个字符为。

      【讨论】:

      • 这将打破简单、可重用和可插入的目的。还是谢谢
      猜你喜欢
      • 2017-05-22
      • 1970-01-01
      • 2016-09-12
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-14
      相关资源
      最近更新 更多