从平面结构到嵌套结构的XSLT转换

4

我无法处理简单的XSLT转换。

存在一个扁平结构的输入XML:

<root>
    <attribute_a>abc</attribute_a>
    <attribute_b>def</attribute_b>
    <attribute_c>ghi</attribute_c>
    <attribute_a>123</attribute_a>
    <attribute_b>456</attribute_b>
    <attribute_c>789</attribute_c>
    <attribute_a>xxx</attribute_a>
    <attribute_b>xxx</attribute_b>
    <attribute_c>xxx</attribute_c>
</root>

我应该将它转换为如下的XML格式:
<root>
    <attribute>
        <attribute_a>abc</attribute_a>
        <attribute_b>def</attribute_b>
        <attribute_c>ghi</attribute_c>
    </attribute>
    <attribute>
        <attribute_a>123</attribute_a>
        <attribute_b>456</attribute_b>
        <attribute_c>789</attribute_c>
    </attribute>
    <attribute>
        <attribute_a>xxx</attribute_a>
        <attribute_b>xxx</attribute_b>
        <attribute_c>xxx</attribute_c>
    </attribute>
</root>

但问题是,像这样进行转换后:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="/">
        <root>
            <xsl:for-each select="root/attribute_a">
                <attribute>
                    <attribute_a>
                        <xsl:value-of select="../attribute_a" />
                    </attribute_a>
                    <attribute_b>
                        <xsl:value-of select="../attribute_b" />
                    </attribute_b>
                    <attribute_c>
                        <xsl:value-of select="../attribute_c" />
                    </attribute_c>
                </attribute>
            </xsl:for-each>
        </root>
        <xsl:apply-templates />
    </xsl:template>
</xsl:stylesheet>

我得到了类似这样的东西:
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <attribute>
        <attribute_a>abc</attribute_a>
        <attribute_b>def</attribute_b>
        <attribute_c>ghi</attribute_c>
    </attribute>
    <attribute>
        <attribute_a>abc</attribute_a>
        <attribute_b>def</attribute_b>
        <attribute_c>ghi</attribute_c>
    </attribute>
    <attribute>
        <attribute_a>abc</attribute_a>
        <attribute_b>def</attribute_b>
        <attribute_c>ghi</attribute_c>
    </attribute>
</root>

我在XSLT方面经验不够 - 你有什么想法?:(

祝好, A. M.


1
欢迎来到SO。感谢您提出了一个结构良好的第一个问题。 :) - Dan Blows
1个回答

2
这应该就可以解决问题了:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="/">
    <root>
      <xsl:for-each select="root/attribute_a">
        <xsl:variable name="pos" select="position()"/>
        <attribute>
          <xsl:apply-templates
            select="../attribute_a[$pos] | 
                    ../attribute_b[$pos] |
                    ../attribute_c[$pos]" />
        </attribute>
      </xsl:for-each>
    </root>
  </xsl:template>
</xsl:stylesheet>

我建议更进一步,使用单独的模板而不是 for-each:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="/">
    <root>
      <xsl:apply-templates select="root/attribute_a" mode="group" />
    </root>
  </xsl:template>

  <xsl:template match="attribute_a" mode="group">
    <xsl:variable name="pos" select="position()"/>
    <attribute>
      <xsl:apply-templates
        select="../attribute_a[$pos] | ../attribute_b[$pos] | ../attribute_c[$pos]" />
    </attribute>
  </xsl:template>
</xsl:stylesheet>

当运行这两个XSLT之一时,针对您的示例输入,它会生成以下输出:
<root>
  <attribute>
    <attribute_a>abc</attribute_a>
    <attribute_b>def</attribute_b>
    <attribute_c>ghi</attribute_c>
  </attribute>
  <attribute>
    <attribute_a>123</attribute_a>
    <attribute_b>456</attribute_b>
    <attribute_c>789</attribute_c>
  </attribute>
  <attribute>
    <attribute_a>xxx</attribute_a>
    <attribute_b>xxx</attribute_b>
    <attribute_c>xxx</attribute_c>
  </attribute>
</root>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接