使用XSLT展平嵌套XML元素的属性

时间:2018-03-12 19:50:54

标签: xml xslt

我试图通过使用XSLT组合属性的值来展平嵌套XML元素的树。例如,如果我有以下输入:

<node value="a">
    <node value="b">
        <node value="c">
            <node value="d">
            </node>
        </node>
        <node value="e">
            <node value="f">
            </node>
            <node value="g">
                <node value="h">
                </node>
            </node>
        </node>
    </node>
</node>

然后这些将是&#34;扁平化的&#34;结果我希望能够得到:

a/b/c/d
a/b/e/f
a/b/e/g/h

我目前所能实现的只是在最深层嵌套的节点&#34;节点&#34;上输出记录。用&#34;值&#34;属性:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:csv="csv:csv">
    <xsl:output method="text" encoding="utf-8" />
    <xsl:template match="text()|@*"/>
    <xsl:template match="node[@value]">
        <xsl:if test="not(descendant::node[@value])">
            <xsl:value-of select="@value"/>
            <xsl:text>&#xa;</xsl:text>
        </xsl:if>
        <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>

正如您从我的描述和xsl:if测试中收集到的那样,一个潜在的复杂因素是&#34;节点&#34;元素可能没有&#34;值&#34;属性,所以必须明确检查。如何更新此样式表以获得所需的结果?

1 个答案:

答案 0 :(得分:2)

使用XSLT 2或3,它变为

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">

  <xsl:output method="text"/>

  <xsl:template match="/">
      <xsl:value-of select="descendant::node[@value and not(descendant::node[@value])]!string-join(ancestor-or-self::node/@value, '/')" separator="&#10;"/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/b4GWVh/0

使用XSLT 1我会使用

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="text"/>

  <xsl:template match="/">
      <xsl:apply-templates select="descendant::node[@value and not(descendant::node[@value])]"/>
  </xsl:template>

  <xsl:template match="node">
      <xsl:apply-templates select="ancestor-or-self::node/@value"/>
      <xsl:text>&#10;</xsl:text>
  </xsl:template>

  <xsl:template match="@value">
      <xsl:if test="position() > 1">/</xsl:if>
      <xsl:value-of select="."/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/b4GWVh/1