XSLT:将父节点属性值与子节点属性值递归连接

时间:2018-09-07 12:32:01

标签: xml xslt

我想将节点的参数值与其父节点的相同参数值递归连接。

示例,如下:

<node name="root">
  <node name="A">
    <node name="B">
      <node name="C">
        <value1>12</value1>
        <value2>36</value1>
      </node>
    </node>
  </node>
</node>

应该成为

<node name="root">
  <node name="root.A">
    <node name="root.A.B">
      <node name="root.A.B.C">
        <value1>12</value1>
        <value2>36</value1>
      </node>
    </node>
  </node>
</node>

我尝试过

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="node/@name">
  <xsl:choose>
    <xsl:when test=". = 'root'">
      <xsl:attribute name="name"><xsl:text>webshop</xsl:text></xsl:attribute>
    </xsl:when>
    <xsl:when test="not(. = 'root')">
      <xsl:attribute name="name"><xsl:value-of select="../../@name"/>.<xsl:value-of select="../@name"/></xsl:attribute>
    </xsl:when>
  </xsl:choose>
</xsl:template>

但是结果不是预期的。我得到的是

<node name="root">
  <node name="root.A">
    <node name="A.B">
      <node name="B.C">
        <value1>12</value1>
        <value2>36</value1>
      </node>
    </node>
  </node>
</node>

出什么问题了?

1 个答案:

答案 0 :(得分:1)

XSLT对输入文档进行操作以生成新的输出文档。输入文档本身将保持不变。当您执行xsl:value-of(或任何其他XSLT操作)时,将在输入文档中进行选择。因此,您正在向name属性添加值的事实根本不会影响您的xsl:value-of语句。

您可以做的是使用一个简单的xsl:for-each获取所有祖先节点并从中建立name属性:

<xsl:for-each select="ancestor::node">
  <xsl:if test="position() > 1">.</xsl:if>
  <xsl:value-of select="@name" />
</xsl:for-each>

尝试使用此XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="node/@name">
    <xsl:attribute name="name">
      <xsl:choose>
        <xsl:when test=". = 'root'">webshop</xsl:when>
        <xsl:otherwise>
          <xsl:for-each select="ancestor::node">
            <xsl:if test="position() > 1">.</xsl:if>
            <xsl:value-of select="@name" />
          </xsl:for-each>
       </xsl:otherwise>
      </xsl:choose>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

如果您可以使用XSLT 2.0,则可以将xsl:for-each替换为单个xsl:value-of

<xsl:value-of select="ancestor::node/@name" separator="." />

(在XSLT 1.0中,xsl:value-of仅输出集合中的第一个节点)