开发者

XSLT Grouping within sub groups using generate-id() is discarding repeat keys from earlier groups

I'm having trouble producing rolled-up groups when the keys I need can be repeated across groups from my input file. I'm using the muenchian method to do the grouping, as I'm stuck with xslt 1.0, and I can't change the input schema.

<groups>
 <group id="1">
     <members>
         <member name="A">
           <udf @name="key">1</customId> 
         </member>
         <member name="B">
           <udf @name="key">1</customId> 
         </member>
     </members>
 </group>
 <group id="2">
     <members>
         <member name="C">
           <udf @name="key">1</customId> 
         </member>
         <member name="D">
           <udf @name="key">2</customId> 
         </member>
         <member name="E">
           <udf @name="key">3</customId> 
         </member>
     </members>
 </group>
</groups>

The output I want to produce is:

<group id="1">
    <member key="1" />
</group>
<group id="2">
    <member key="1" />
    <member key="2" />
    <member key="3" />
</group>

I'm also doing other processing on each element as well, but that is tangential.

I have a template that runs a loop and generates a key:

<xsl:tempalte name="process">
   <xsl:for-each select="groups/group">
      <xsl:call-template name="getMembers"/>
   </xsl:for-each>
</xsl:tempalte>

<xsl:key name="keyId" match="member" use="udf/@name[.='key']/.."/>

<xsl:template name="getMembers>
    <xsl:for-each select="members/member[generate-id() = generate-id(key('keyId',udf/@name[.='key']/..))]">
      <!-- emits the grouped tags. -->
    </xsl:for-each>
</xsl:template>

So far, what I'm getting with this transform is:

<gro开发者_JAVA百科up id="1">
    <member key="1" />
</group>
<group id="2">
    <member key="2" />
    <member key="3" />
</group>

..you'll see its missing key 1 out of group 2. So, I'm confused as to why the 2nd time the template is called, the generate id function is not emitting a new unique key for value "1", even though I'm calling generate id within the context i thought, of group 2.


You need to use a concatenated key that takes the group or members parent into account e.g.

<xsl:key name="keyId" match="member" use="concat(generate-id(parent::members/parent::group), '|', udf[@name = 'key'])"/>

then of course anywhere where you use the key function you need to ensure you compute it with the same expression e.g.

<xsl:for-each select="members/member[generate-id() = generate-id(key('keyId', concat(generate-id(parent::members/parent::group), '|', udf[@name = 'key'])))]">
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜