Jim, First of all i should appreciate you getting really good questions on to the forum. I've not prepared the xsl:keys and need to do that; I was a little busy trying to write some code for the schema question put up today; I need to take some time to understand keys first and then may be will get into a position to answer this. So i look forward to hear from Dan or anybody on this forum for an answer to this.

jim yin

Ranch Hand

Posts: 111

posted 17 years ago

Javadev, you are doing very well in terms of understanding basic concepts. Well, this test covers too much ground, it is really hard to get deeper.

This code is retreiving elements for a unique combination of attribute and element value The data retreived is according to this pattern: M1mouse M2 mouse K1 keyboard M2 keyboard K2 keyboard Hence it gets a count of only 5 elements.

Can you please be a little more elaborate in your explanation, like what the key exactly means here, how is it being used and what the template matching a text() node is doing here. That would be a lot of help for me as i'm key-ignorant Thanks again.

I think Vasudha is right. In addition, the code returns the _first_ five unique combinations of attribute and element values. Jayadev, the template matching a text() node is there to suppress output from other text nodes which are not covered by the ItemName rule. I’m still trying to figure it all Cheers, Dan

William Butler Yeats: All life is a preparation for something that probably will never happen. Unless you make it happen.

<xsl:key name="kCodeValue" match="ItemName" use="concat(@code,'::', .)"/> This would give us a set of ItemName nodes with their respective key values as follows (as Vasudha pointed out earlier) - ItemName[0] M1::Mouse ItemName[1] M2::Mouse ItemName[2] K1::KeyBoard ItemName[3] M1::Mouse ItemName[4] M2::KeyBoard ItemName[5] K2::KeyBoard ItemName[6] K1::KeyBoard This node-set will be having "kCodeValue" as its key name and the values shown above as repective key values. Now if we say something like - <xsl:for-each select="key("kCodeValue", "M1::Mouse")>..... Here nodes ItemName[0] and ItemName[3]will be selected by the above xsl statement. I think the entire things lies around this count() function - <xsl:template match="ItemName[count(.| key('kCodeValue',concat(@code,'::', .))[1])=1]"> <xsl:copy-of select="."/> </xsl:template> Not completely clear about what this is doing!!!

Jayadev Pulaparty

Ranch Hand

Posts: 662

posted 17 years ago

Dan, I misread the text() node part. I got crazy thinking that all the count() stuff is lying inside the template match for text(). Sorry for that. Coming to the uniqueness of node,key-value pairs, i'm pretty sure that values are being repeated in the node-set as part of the keyname. Just try this little xsl on the source xml and you will come to know this - <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; <xsl utput indent="yes" omit-xml-declaration="yes"/> <xsl:key name="kCodeValue" match="ItemName" use="concat(@code,'::', .)"/> <xsl:template match="/"> <xsl:for-each select="key('kCodeValue', 'M1::Mouse')"> <p> <xsl:value-of select="@code"/> <xsl:value-of select="."/> </p> </xsl:for-each> </xsl:template> <xsl:template match="text()"/> </xsl:stylesheet>

jim yin

Ranch Hand

Posts: 111

posted 17 years ago

ItemName[0] M1::Mouse ItemName[1] M2::Mouse ItemName[2] K1::KeyBoard ItemName[3] M1::Mouse ItemName[4] M2::KeyBoard ItemName[5] K2::KeyBoard ItemName[6] K1::KeyBoard This node-set will be having "kCodeValue" as its key name and the values shown above as repective key values. Now if we say something like - <xsl:for-each select="key("kCodeValue", "M1::Mouse")>..... Here nodes ItemName[0] and ItemName[3]will be selected by the above xsl statement. I think the entire things lies around this count() function - <xsl:template match="ItemName[count(.| key('kCodeValue',concat(@code,'::', .))[1])=1]"> <xsl:copy-of select="."/> </xsl:template>

My understanding is: key() function will fetch the matched items from the above list first, key(...)[1] will get the first one from the list. "." in count() function will get the current item. "|" is used to eliminate the duplicates if the current node is the same as the first in the list. What I don't understand is: Key() function will produce a list of key-value pairs, while the "." will only get the value since text() will only gives us values. How can they compare with each other?

Jayadev Pulaparty

Ranch Hand

Posts: 662

posted 17 years ago

Jim, I guess this is what is happening. First of all duplicates are being allowed as the key values. ItemName[count(.| key('kCodeValue',concat(@code,'::', .))[1])=1]"> By count(. here means the current context of the ItemName node and key('kCodeValue',concat(@code,'::', .)) will return a node-set of 2 nodes for the repeating ones. By saying key('kCodeValue',concat(@code,'::', .))[1], i think we are comparing the current context of ItemName node(.) to be always equal to the first one in the key list. This is enforcing the condition of uniqueness. Not really sure that the | is doing there !!! I need to understand it further

Jayadev Pulaparty

Ranch Hand

Posts: 662

posted 17 years ago

Try to replace the relevant stuff with this and you see only the nodes that are repeated 2 times in the output <xsl:template match="ItemName[count(.| key('kCodeValue',concat(@code,'::', .))[1])=2]"> <xsl:copy-of select="."/> </xsl:template> Still not very sure as to how this mechanism is working

jim yin

Ranch Hand

Posts: 111

posted 17 years ago

key('kCodeValue',concat(@code,'::', .)) will return a node-set of 2 nodes for the repeating ones. By saying key('kCodeValue',concat(@code,'::', .))[1], i think we are comparing the current context of ItemName node(.) to be always equal to the first one in the key list. This is enforcing the condition of uniqueness.

"|" means union. I think I got it, key() actually produces a list of text values, and "." fetches the current node's text value, how do we compare? They will always be equal, yes.

Dan Drillich

Ranch Hand

Posts: 1183

posted 17 years ago

Jim,

"|" means union

Looks more like OR to me :roll:

William Butler Yeats: All life is a preparation for something that probably will never happen. Unless you make it happen.

Jayadev Pulaparty

Ranch Hand

Posts: 662

posted 17 years ago

Friends, Just run the following stylesheet on the xml file to get the output. Analysis of the things follows - XSL stylesheet - <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; <xsl utput indent="yes" omit-xml-declaration="yes"/> <xsl:key name="kCodeValue" match="ItemName" use="concat(@code,'::', .)"/> <xsl:template match="text()"/> <xsl:template match="ItemName"> <p> <xsl:value-of select="count(.|key('kCodeValue',concat(@code,'::', .))[1])"/> </p> </xsl:template> </xsl:stylesheet> OUTPUT _______ <p>1</p> <p>1</p> <p>1</p> <p>2</p> <p>1</p> <p>1</p> <p>2</p> Analysis of the stuff - _________________________ The key generates the following (node,keyvalue) pairs - ItemName[1] M1::Mouse ItemName[2] M2::Mouse ItemName[3] K1::KeyBoard ItemName[4] M1::Mouse ItemName[5] M2::KeyBoard ItemName[6] K2::KeyBoard ItemName[7] K1::KeyBoard Now the template match ItemName[....] is checking for the ItemName element for the predicate given in the brackets to be true and then only the template will be executed. I guess everything is clear till this point. Now the whole point here is that count(.|key('kCodeValue',concat(@code,'::',.))[1]) will look at the current context node and also checks for the node represented by key('kCodeValue',concat(@code,'::',.))[1] "If they are same,(w.r.t both their context(location)in the tree and the content), only one of them will be taken by the count() function and the count will be 1. If they are different, the count will be 2." This is exactly why we are seeing the count value to be 2 for the succeeding occurences of the ItemName nodes eventhough they have the same content eg., M1::Mouse as their context will not match the Node of occurence[1] in the key nodeset.