Group/merge childs of same nodes in xml/xslt when

2019-09-20 01:39发布

As an addition to my orginal post Group/merge childs of same nodes in xml/xslt I ran into the problem of having that structure repeated multiple times for different nodes (wihtin nodes higher in the hierarchy) e.g.,

<Collection>
    <Questionnaire Name="Preferences" VersionID="3QW">
        <Subject ID="2355">
            <EventData Name="First Part">
                <FormData Name="Past">
                    <GroupData ID="xxx" Key="4" Temp="yyy">
                        <ItemData ID="zzz" Value="3"/>
                    </GroupData>
                    <GroupData ID="xxx" Key="4" Temp="yyy">
                        <ItemData ID="qqq" Value="4"/>
                    </GroupData>
                    ...
                </FormData>
                <FormData Name="Present">
                    <GroupData ID="yyy" Key="9" Temp="yyy">
                        <ItemData ID="www" Value="32"/>
                    </GroupData>
                    ...
                </FormData>             
            </EventData>
            <EventData Name="SecondPart">
                ...
            </EventData>
        </Subject>
        <Subject ID="9812">
            ...
        </Subject>
    </Questionnaire>    
</Collection>   

After trying variations on the suggestions I reveived and some other things I am stuck. I think it has something to do with multiple levels (and GroupData being spread over upper/grandparent nodes in which it will be a child) and then it possiblly does not have unique IDs anymore. So how can I get the childs of each GroupData node into one GroupData node (matched on ID and sometimes Key, since the latter is not always present)? Note: The same GroupData nodes (with corresponding attributes) must be merged into one GroupData node in each FormData node.

标签: xslt nodes
1条回答
Melony?
2楼-- · 2019-09-20 02:15

Here are two XSLT 1.0 solutions.

One solution is to take Dimite's solution from your first question, and just expand the key to include FormData...

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

 <xsl:key name="kGDByIdKey" match="FormData/GroupData"
  use="concat(@ID, '+', @Key, '+', generate-id(..))"/>

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

 <xsl:template match=
 "FormData/GroupData
    [generate-id()
    =
     generate-id(key('kGDByIdKey', concat(@ID, '+', @Key, '+', generate-id(..)))[1])
     ]">
    <xsl:copy>
      <xsl:apply-templates select=
       "@*|key('kGDByIdKey', concat(@ID, '+', @Key, '+', generate-id(..)))/node()"/>
    </xsl:copy>
 </xsl:template>

  <xsl:template match="GroupData"/>
</xsl:stylesheet>

Another solution moves the grouping test from the template match condition to the the invoking xsl:apply-templates in the parent FormData ...

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

 <xsl:key name="kGDByIdKey" match="FormData/GroupData" use="concat(@ID, '+', @Key)" />

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

 <xsl:template match="FormData">
     <xsl:copy>
       <xsl:apply-templates select="
          @* |
          node()[not(self::GroupData)] |
          GroupData[generate-id() =
                    generate-id(key('kGDByIdKey', concat(@ID, '+', @Key))[1])]"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="FormData/GroupData">
     <xsl:copy>
       <xsl:apply-templates select="@*|
           key('kGDByIdKey', concat(@ID, '+', @Key))/node()"/>
     </xsl:copy>
 </xsl:template>
  <xsl:template match="GroupData"/>
</xsl:stylesheet>

Both stylesheets assume that GroupData's parent is only ever FormData. Any GroupData which does not have a FormData parent is removed.

查看更多
登录 后发表回答