0

我有这样的 XSLT 1.0:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="paragraph">
    <p>
      <xsl:apply-templates/>
    </p>
  </xsl:template>
</xsl:stylesheet>

只是,有很多很多模板与第一个类似。我想在这些模板中的每一个中发出一个特定的属性,但我想做出最小侵入性的改变来实现它。这是我尝试的第一件事:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="paragraph">
    <p>
      <xsl:apply-templates/>
    </p>
  </xsl:template>

  <xsl:template match="@class">
    <xsl:attribute name="class">
      <xsl:value-of select="@class"/>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

但这没有用。我试过这个:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="paragraph">
    <p>
      <xsl:attribute name="class">
        <xsl:value-of select="@class"/>
      </xsl:attribute>
      <xsl:apply-templates/>
    </p>
  </xsl:template>
</xsl:stylesheet>

但是要在每个模板中实现这一点,需要大量的代码重复。这是我能做的最好的事情,还是有更合适的方法来完成这项工作?

4

2 回答 2

2

如果您真的不想对现有的模板规则进行任何更改,则添加一个优先级高于“p”等规则的模板规则,如下所示:

<xsl:template match="*[@class]" priority="100">
  <xsl:variable name="v">
    <xsl:next-match/>
  </xsl:variable>
  <xsl:apply-templates select="$v" mode="add-attribute">
    <xsl:with-param name="att" select="@class"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="*" mode="add-attribute">
  <xsl:param name="att" as="attribute()"/>
  <xsl:copy>
     <xsl:copy-of select="@*, $att"/>
     <xsl:apply-templates mode="#current"/>
  </xsl:copy>
</xsl:template>

在 1.0 中,您必须将其放在单独的模块中并使用 apply-imports 而不是 next-match。

于 2012-09-20T08:06:32.990 回答
2

在您最初的尝试中

  <xsl:template match="@class">
    <xsl:attribute name="class">
      <xsl:value-of select="@class"/>
    </xsl:attribute>
  </xsl:template>

此模板的上下文节点是class属性节点,因此value-of应该选择.

  <xsl:template match="@class">
    <xsl:attribute name="class">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

但是,您还应该注意,bare<xsl:apply-templates/>仅应用与当前节点的节点匹配的模板,并且由于属性节点在 XSLT 数据模型中不算作子节点,因此该@class模板不会触发。你可能需要修改你的paragraph模板说

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

应用匹配paragraph元素属性及其子元素的模板。

于 2012-09-19T22:30:15.373 回答