如何修复此XSLT以将此XML节点分组为具有特定属性的父节点?

时间:2012-05-26 14:52:03

标签: xml xslt

我需要将此节点合并在一起,但必须与具有属性method="a"的父级合并

输入:

<myroot>
    <elem name="a" creationDate="">
        <list id="xxx" ver="uu">
            <nodeA id="a">
                <fruit id="small">
                    <orange id="x" method="create">                       
                        <color>Orange</color>                                               
                    </orange>
                </fruit>     
                <fruit id="small" method="a">
                    <kiwi id="y" method="create">                        
                        <color>Red</color>
                        <type>sour</type>                       
                    </kiwi>                    
                </fruit>
                <fruit id="large" method="a">
                    <melon id="y" method="create">
                        <attributes>
                            <color>Green</color>
                            <type>sweet</type>
                        </attributes>
                    </melon>                    
                </fruit>
            </nodeA>
        </list>
    </elem>
</myroot>

我的XSL文件:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="list">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:for-each-group select="/*/*/*/*" group-by="@id">
                <xsl:copy>
                    <xsl:copy-of select="@*"/>
                    <xsl:for-each-group select="current-group()/*" group-by="concat(local-name(), '|', @id)">
                        <xsl:copy>
                            <xsl:apply-templates select="@*, *, (current-group() except .)/*"/>
                        </xsl:copy>
                    </xsl:for-each-group>
                </xsl:copy>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

我的输出:

<myroot>
    <elem name="a" creationDate="">
        <list id="xxx" ver="uu">
            <nodeA id="a">
                <fruit id="small">            
                    <orange id="x" method="create">                       
                        <color>Orange</color>                                               
                    </orange>
                    <kiwi id="y" method="create">                        
                        <color>Red</color>
                        <type>sour</type>                       
                    </kiwi>                    
                </fruit>     

                <fruit id="large" method="a">
                    <melon id="y" method="create">
                        <attributes>
                            <color>Green</color>
                            <type>sweet</type>
                        </attributes>
                    </melon>                    
                </fruit>
            </nodeA>
        </list>
    </elem>
</myroot>

预期输出:

<myroot>
    <elem name="a" creationDate="">
        <list id="xxx" ver="uu">
            <nodeA id="a">
                <fruit id="small" method="a"> <!-- this is the correct merge where the merged is in parent that has a method -->
                    <kiwi id="y" method="create">                        
                        <color>Red</color>
                        <type>sour</type>                       
                    </kiwi>
                    <orange id="x" method="create">                       
                        <color>Orange</color>                                               
                    </orange>
                </fruit>     

                <fruit id="large" method="a">
                    <melon id="y" method="create">
                        <attributes>
                            <color>Green</color>
                            <type>sweet</type>
                        </attributes>
                    </melon>                    
                </fruit>
            </nodeA>
        </list>
    </elem>
</myroot>

正如我们所看到的,我的转换只将它们组合在一起而不考虑方法。如何更改它以便它将合并到示例中为method="a"的{​​{1}}的父<fruit id="small" method="a">

谢谢。 约翰

1 个答案:

答案 0 :(得分:1)

<xsl:for-each-group>元素中,上下文项只是该组的第一个元素,因此select="@*"将仅复制第一个元素的属性。要在任何元素中获取所有不同命名属性的副本,您需要访问current-group()/@*

也不需要select="*, (current-group() except .)/*",因为它等同于select="current-group()/*"

完整的样式表看起来像这样

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

  <xsl:output method="xml" indent="yes" />
  <xsl:strip-space elements="*" />

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

  <xsl:template match="list">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates select="*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="list/*">

      <xsl:copy>

        <xsl:copy-of select="@*" />

        <xsl:for-each-group select="*" group-by="concat(local-name(), '|', @id)">
          <xsl:copy>
            <xsl:copy-of select="current-group()/@*" />
            <xsl:copy-of select="current-group()/*" />
          </xsl:copy>
        </xsl:for-each-group>

      </xsl:copy>

  </xsl:template>

</xsl:stylesheet>