xsl-list
[Top] [All Lists]

Re: XPath Problem.

2003-01-08 14:16:19
Hi Sandeep,

At 02:51 PM 1/8/2003, you wrote:
<RootNode>
<DInfo name="D1">
        <TInfo name="t1"></T1>
        <TInfo name="t2"></T2>
</DInfo>
<DInfo name="D2">
        <DInfo name="D3">
                <TInfo name="t1"></T1>
                <TInfo name="t2"></T2>
        </DInfo>
        <DInfo name="D4">
                <DInfo name="D5">
                        <TInfo name="t3"></T1>
                        <TInfo name="t4"></T2>
                </DInfo>
                <DInfo name="D6">
                        <TInfo name="t3"></T1>
                        <TInfo name="t4"></T2>
                </DInfo>
        </DInfo>
</DInfo>
</RootNode>

Required Output:-
        <xsl:key name="TInfo-Key-By-Name" match="TInfo" use="@name"/>

        <xsl:for-each
select="TInfo[count(.|key('TInfo-Key-By-Name',@name)[1]) = 1]">
                <xsl:call-template name="ShowTInfo">
        </xsl:for-each>
1. So when I have the RootNode Selected this works correctly and displays me
t1, t2, t3 , t4  only once.

2. When I am on <DInfo name="D2"> I need to display t1, t2, t3, t4. However
only t3 and t4 get displayed since it thinks that t1 and t2 have already
been displayed.

Well, not exactly. Only t3 and t4 get displayed since it thinks (correctly) that those are its only descendants that pass the test you have given, which checks whether a TInfo is the first with its name value in the document. In your example, inside DInfo D2, this is the case only for the TInfo children of DInfo D5, not those of DInfo D3.

Keys are useful for deduplicating globally (i.e. within the entire document), but in order to do local de-duplication, you have to think harder. Your condition is apparently not to check a node's name value globally (assuring it's the first in the document), but rather only among the descendants of a particular node. This means comparing the value of its name not to all the TInfo elements, but only those inside a particular descendant ... which is a harder set to select.

Not impossible, however. Here's a template that matches a DInfo and gives back only those TInfo descendants that are first within it:

<xsl:template match="DInfo">
  <xsl:variable name="TInfo-descendants" select=".//TInfo"/>
    <!-- this variable holds all the TInfo elements in our scope:
         we'll need it later -->
  <xsl:for-each select="$TInfo-descendants">
    <!-- now we go process each of our TInfo descendants -->
    <xsl:variable name="all-preceding-TInfos"
       select="preceding::TInfo"/>
<!-- this variable collects all TInfos in the document preceding this one -->
    <xsl:variable name="preceding-TInfos"
       select="$TInfo-descendants[count(.|$all-preceding-TInfos) =
                                  count($all-preceding-TInfos)]"/>
<!-- this variable declaration uses an XPath idiom to get an intersection between the two sets of TInfos, resulting in all the TInfo elements in scope that
         precede this one -->
    <xsl:if test="@name = $preceding-TInfos/@name">
<!-- the test will only allow a TInfo through that has a name not on one of
           the preceding TInfos -->
      <xsl:call-template name="ShowTInfo">
    </xsl:if>
  </xsl:for-each>
</xsl:template>

Note this approach is liable to be fairly costly over large documents, since it has to use the preceding:: axis to find nodes to check against.

Cheers,
Wendell


======================================================================
Wendell Piez                            
mailto:wapiez(_at_)mulberrytech(_dot_)com
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



<Prev in Thread] Current Thread [Next in Thread>