根据父动态属性动态添加属性和设置值

Dynamically add attribute and set value based on parent dynamic attribute

大家好我正在尝试转换这个 xml:

<element>
    <element>
      <element>

      </element>
    </element>
    <element>

    </element>
</element>

为此:

<element test="">
    <element test="f">
      <element test="ff">

      </element>
    </element>
    <element test="f">

    </element>
</element>

所以用 "f" 等连接任何 parent/@test 等等。

我目前有这个 xml:

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

  <xsl:template match="*[not(self::newline or self::tab or self::space)]" mode="copying">
    <xsl:copy>
      <xsl:apply-templates select="@*" mode="copying"/>

      <xsl:attribute name="test">
        <xsl:choose>
          <xsl:when test="parent::*">
            <xsl:value-of select="concat(../@test,'    ')"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="''"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>
      <xsl:apply-templates select="node()" mode="copying"/>
    </xsl:copy>
  </xsl:template>

但它只是忽略了父属性的值。有人可以帮我吗?

通过 XSLT 2.0,您可以使用

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

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

    <xsl:template match="*[not(self::newline or self::tab or self::space)]">
        <xsl:param name="test" tunnel="yes" select="''"/>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="test" select="$test"/>
            <xsl:apply-templates select="node()">
                <xsl:with-param name="test" tunnel="yes" select="concat($test, 'f')"/>
            </xsl:apply-templates>
        </xsl:copy>

    </xsl:template>
</xsl:transform>

对于 XSLT 1.0,您需要确保标识转换模板(第一个模板)以及您可能传递参数的所有其他模板:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:template match="@*|node()">
        <xsl:param name="test"/>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()">
                <xsl:with-param name="test" select="concat($test, 'f')"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[not(self::newline or self::tab or self::space)]">
        <xsl:param name="test" select="''"/>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="test">
                <xsl:value-of select="$test"/>
            </xsl:attribute>
            <xsl:apply-templates select="node()">
                <xsl:with-param name="test" select="concat($test, 'f')"/>
            </xsl:apply-templates>
        </xsl:copy>

    </xsl:template>
</xsl:transform>