Presentation is loading. Please wait.

Presentation is loading. Please wait.

Lecture 21.

Similar presentations


Presentation on theme: "Lecture 21."— Presentation transcript:

1 Lecture 21

2 Keys in XSLT We have already seen one way to process documents that contain an implicit cross-reference structure - the use of XSLT variables However, XSLT provides another type of tool, called a key, for this sort of task Keys are created using the xsl:key element Then the keys are used through the key() function Before we consider the use of keys, the next slide reminds us how we used variables to handle cross-reference The we will use a set of keys to handle the same task Subsequent slides will consider keys in more detail

3 Reminder: using an xsl:variable element to handle cross-references
<?xml version="1.0"?> <xsl:transform version="1.0" xmlns:xsl=" <xsl:template match="/"> <html> <head><title>Second-hand books</title></head> <body> <table rules="all"> <thead><tr><th>Price</th><th>ISBN</th><th>Title</th></tr></thead> <tbody> <xsl:for-each select="./stock/secondHandBooks/book"> <xsl:variable name="thisISBN” <tr><td><xsl:value-of select="price"/></td> <td> <xsl:value-of select="$thisISBN"/> </td><td> <xsl:value-of select=" </xsl:for-each> </tbody> </table></body></html> </xsl:template> </xsl:transform>

4 Using keys for this task: part 1, the stylesheet
We use xsl:key to create a set of keys, each of which has the name abstractbook, and points to a node which has an XPath of the form /stock/publications/pub uses the isbn attribute of each such node to identify the appropriate node Later, through the key() function, we use the isbn attribute of each second-hand book to access the title of the publication which has this isbn <?xml version="1.0"?> <xsl:transform version="1.0" xmlns:xsl=" <xsl:key name="abstractBook" match="/stock/publications/pub" <xsl:template match="/"> <html> <head><title>Second-hand books</title></head> <body> <table rules="all"><thead><tr><th>Price</th> <th>ISBN</th><th>Title</th></tr></thead> <tbody> <xsl:for-each select="./stock/secondHandBooks/book"> <tr><td><xsl:value-of select="price"/></td> <td> <xsl:value-of </td> <td> <xsl:value-of </td> </tr> </xsl:for-each> </tbody> </table></body></html> < /xsl:template> </xsl:transform>

5 Using keys for this task: part 2, the complete scenario
<?xml version="1.0"?> <xsl:transform version="1.0" xmlns:xsl=" <xsl:key name="abstractBook" match="/stock/publications/pub" <xsl:template match="/"> <html> <head><title>Second-hand books</title></head> <body> <table rules="all"> <thead><tr><th>Price</th><th>ISBN</th><th>Title</th></tr></thead> <tbody> <xsl:for-each select="./stock/secondHandBooks/book"> <tr><td><xsl:value-of select="price"/></td> <td> <xsl:value-of </td><td> <xsl:value-of </xsl:for-each> </tbody> </table></body></html> </xsl:template> </xsl:transform>

6 The xsl:key element The xsl:key element must be a top-level element - a child of the overall stylesheet/transform element It is used to create a set of keys, each which points to some target Each target is a set of one or more nodes in the parse tree of the document being processed by the stylesheet (In the previous example, each target contained exactly one publication but, in general, a target set can contain more than one member.) The xsl:key element is of the form <xsl:key name="..."  match="..."  use="..." /> The match attribute is used to identify some set of nodes The use attribute specifies a property whose value will be used to divide the set of nodes into subsets, each subset being a target for one key We may NOT refer to a variable in the match or use attributes

7 The key() function (a simple view)
We use the key() function to access the targets of keys that were created by using the xsl:key element A call to the function is of the form key(nameOfSomeSetOfKeys, someObject) The first argument is the name used for some set of keys There are several possibilities for the second argument But, for now, we will just consider the simple case where the second argument is a string

8 Simple example 1 Here, we create one set of keys
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" ><xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" <xsl:template match="/"> <xsl:value-of select="count(key('myKey','fred'))"/> <br/> select="count(key('myKey','geo'))"/> </xsl:template> </xsl:transform> Here, we create one set of keys Each key points to a subset of the nodes that have XPath /root/t1 The nodes are grouped by checking their a attribute Since nodes with the specified XPath have two different values for the specified attribute, two keys are created The target for the first key is a set of three nodes The target for the second key is (a set containing) one node

9 More on the simple view of the key() function
As we have seen, a call to the function is of the form key(nameOfSomeSetOfKeys, someObject) As we have seen, the first argument is the name used for some set of keys When the second argument is a string, the key() function returns the set of nodes targeted by whatever key, in the named set of keys, was created by a use attribute that had this string as its value Thus, in the stylesheet on the previous slide. the call key('myKey','fred') returned a set of three nodes because there are three nodes in the target associated with the key created using the value fred for the a attribute

10 Simple example 2 <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" ><xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" <xsl:template match="/"> <xsl:for-each select="key('myKey','fred')"> <xsl:value-of select="."/> <br/> </xsl:for-each> <hr/> </xsl:template> </xsl:transform> Here, we create the same set of keys as in the last example But, this time, we output the string values of the individual nodes in the target set for the first key and the string value of the single node in the target set for the second key

11 Simple example 3 <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" ><xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" <xsl:template match="/"> <xsl:value-of select="key('myKey','fred')[position()=2]"/> <br/> select="key('myKey','geo')[position()=1]"/> </xsl:template> </xsl:transform> Since the key() function returns a node set, we can use position() to access individual nodes in the target associated with some key Here, we create the same set of keys as in the last example But, this time, we output the string value of the second individual node in the target set for the first key and the string value of the first (only) node in the target set for the second key

12 Simple example 4: keys can point to attribute nodes
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" use="."/> <xsl:template match="/"> <xsl:for-each select="key('myKey','fred')"> The nationality of <xsl:value-of select=".."/> is <xsl:value-of <br/> </xsl:for-each> <hr/> <xsl:for-each select="key('myKey','geo')"> </xsl:template> </xsl:transform> Here, we create a set of keys pointing to nodes representing nickname attributes and using the value of each nickname to assign the node to a target Then, we process each key, by listing the parent node of each node in the key's target set When listing each parent node, we also output the country attribute of the parent

13 Simple example 5: target scattered around the parse tree
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" ><xsl:output method="html" /> <xsl:key name="myKey" match="//t1" <xsl:template match="/"> <xsl:for-each select="key('myKey','fred')"> <xsl:value-of select="."/> <br/> </xsl:for-each> <hr/> </xsl:template> </xsl:transform> The nodes associated with a key can be scattered throughout the parse tree Here, we see that some nodes in the target for the first key are children of the root element but another node is a grand-child Also, one node in the target for the second key is a child of the root element but other nodes are grand-children

14 Simple example 6: a node can be in several targets
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" ><xsl:output method="html" /> <xsl:key name="myKey1" match="//t1" <xsl:key name="myKey2" match="//t1" <xsl:template match="/"> <xsl:for-each select=" key('myKey1','fred') "><xsl:value-of select="."/> <br/></xsl:for-each><hr/><xsl:for-each select="key('myKey1','geo')"><xsl:value-of select="."/> <br/></xsl:for-each> <hr/> <hr/> <xsl:for-each select="key('myKey2','uk')"><xsl:value-of select="."/> <br/></xsl:for-each> <hr/> <xsl:for-each select="key('myKey2','de')"><xsl:value-of select="."/> <br/></xsl:for-each> <xsl:for-each select="key('myKey2','ru')"><xsl:value-of select="."/> <br/></xsl:for-each> </xsl:template> </xsl:transform> Here, we create two sets of keys there are two keys in the first set there are three keys in the second set We see that a node can be in the target for several keys For example, the Gyorgy node is in the target for the second key of the first set and in the target for the third key of the second set

15 Simple example 7: the use attribute can specify an element node
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" use="a" /> <xsl:template match="/"> <xsl:for-each select="key('myKey','fred')"> <xsl:value-of select="."/> <br/> </xsl:for-each> <hr/> <xsl:for-each select="key('myKey','geo')"> </xsl:template> </xsl:transform Here, the t1 elements do not have an a attribute; instead, each has a child element with tagname a We can use these children elements to create the keys

16 Simple example 8: the use attribute can specify a node set
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" use="a"/> <xsl:template match="/"> <xsl:for-each select="key('myKey',' fred')"> <xsl:value-of select="."/> <br/></xsl:for-each> <hr/> <xsl:for-each select="key('myKey','geo')"> <xsl:for-each select="key('myKey','rick')"> <xsl:for-each select="key('myKey',' alf')"> </xsl:template> </xsl:transform> Here, the xsl:key element is the same as in the previous example <xsl:key name="myKey" match="/root/t1" use="a"/> However, some t1 elements have several a child elements that is, the use attribute specifies a set of nodes When the use attribute specifies a node-set, a key is created for the string value of each node in the node set Thus, there are four keys, one each for fred rick geo and alf

17 That is, one for each node in /root/t1/a
Example 9 - suppose we did not want to manually list each possible key string <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" use="a"/> <xsl:template match="/"> <xsl:for-each select="/root/t1/a"> The target for <strong><xsl:value-of select="."/></strong> is <br/> <xsl:for-each select=" key('myKey', . ) "> <xsl:value-of select="."/> <br/> </xsl:for-each> <hr/> </xsl:template> </xsl:transform> In the last example, there were four keys, one each for fred rick geo and alf That is, one for each node in /root/t1/a Suppose we want to avoid having to manually mention fred rick geo and alf in our stylesheet We might consider using a nesting for-each element like that in this stylesheet

18 That is, one for each node in /root/t1/a
Example 9 - suppose we did not want to manually list each possible key string <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" use="a"/> <xsl:template match="/"> <xsl:for-each select="/root/t1/a"> The target for <strong><xsl:value-of select="."/></strong> is <br/> <xsl:for-each select=" key('myKey', . ) "> <xsl:value-of select="."/> <br/> </xsl:for-each> <hr/> </xsl:template> </xsl:transform> In the last example, there were four keys, one each for fred rick geo and alf That is, one for each node in /root/t1/a Suppose we want to avoid having to manually mention fred rick geo and alf in our stylesheet We might consider using a nesting for-each element like that in this stylesheet But the target for one key is listed more than once

19 The problem in the last slide
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" use="a"/> <xsl:template match="/"> <xsl:for-each select="/root/t1/a"> The target for <strong><xsl:value-of select="."/></strong> is <br/> <xsl:for-each select=" key('myKey', . ) "> <xsl:value-of select="."/> <br/> </xsl:for-each> <hr/> </xsl:template> </xsl:transform> The problem here is that <xsl:for-each select="/root/t1/a"> processes every member of the node set denoted by the XPath /root/t1/a But we want to process only the distinct members of the node set It is easy to do this with a new function, called distinct-values(), that is defined in XPath 2.0 However, no browser yet supports XPath2.0 However, as we will see later, there is a work-around

20 The key() function - a more complete view

21 The key() function - towards a complete view
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" use="a"/> <xsl:template match="/"> <xsl:for-each select="/root/t1/a"> The target for <strong><xsl:value-of select="."/></strong> is <br/> <xsl:for-each select=" key('myKey', . ) "> <xsl:value-of select="."/> <br/> </xsl:for-each> <hr/> </xsl:template> </xsl:transform> Earlier, we used only a string as the second argument for the key() function But the last stylesheet slipped in a feature of the function that we had not considered before In the stylesheet, the element <xsl:for-each select=" key('myKey', . ) "> <xsl:value-of select="."/> <br/> </xsl:for-each> used a (singleton) node-set for this second argument

22 The key() function - a complete view
We use the key() function to access the targets of keys that were created by using the xsl:key element A call to the function is of the form key(nameOfSomeSetOfKeys, someObject) The first argument is the name used for some set of keys Before, we considered just the simple case where the second argument is a string However, the full situation is this: if the second argument of a call to the key() function is anything other than a node-set, the argument is converted to a string and the call performs in the way that we have seen until now; but, if the second argument of a call to the key() function is a node-set, the result of the call is the union of the result of applying the function to the string value of each of the nodes in the argument node-set; On the next slide, we will consider a simple example of using a node-set argument

23 Simple example 10: a node-set as 2nd argument to key()
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" use="a"/> <xsl:template match="/"> <xsl:for-each select="/root/t1"> Considering the t1 element whose string value is <strong><xsl:value-of select="."/></strong>, we get <br/> <xsl:for-each select="key('myKey',./a)"> <xsl:value-of select="."/> <br/> </xsl:for-each> <hr/> </xsl:template> </xsl:transform> Consider processing the first t1 element The 2nd argument to key() is a node-set containing nodes for the two elements <a>fred</a><a>rick</a> The key for the string 'fred' has a target containing three nodes The key for the string 'rick' has a target containing two nodes The union of these targets contains four nodes

24 The generate-id() function

25 The generate-id() function
XSLT 1.0 includes a function, called generate-id(), which, when given any node in the parse tree, generates a string which uniquely identifies that node in the parse tree

26 Example use of the generate-id() function
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:template match="/"> <xsl:for-each select="/root/t1"> The id generated for <br/> <xsl:value-of select="."/> is <br/> <xsl:value-of select="generate-id(.) "/> <hr/> </xsl:for-each> </xsl:template> </xsl:transform> A unique string is generated for each node passed to the generate-id() function

27 In fact, ... In fact, different unique strings are generated on each occasion the stylesheet is executed

28 The really useful thing about generate-id() is that ...
if, within one execution of a stylesheet, generate-id() is called more than once on an individual node, it generates exactly the same unique string for the node each time <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" ><xsl:output method="html" /><xsl:template match="/"> <xsl:for-each select="/root/t1"> The id generated for <br/> <xsl:value-of select="."/> is <br/> <xsl:value-of select="generate-id(.) "/> <hr/> </xsl:for-each> <hr><br> </xsl:template></xsl:transform>

29 Using generate-id() to produce cross-referenced anchor elements
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:template match="/"> <h1>Index</h1> <xsl:for-each select="/people/person"> <a href="#{generate-id(.)}"> <xsl:value-of select="./name"/></a><br/> </xsl:for-each> <h1>Detailed information</h1> <a name="{generate-id(.)}"> <xsl:value-of select="./name"/>,</a> <xsl:value-of select="./address"/><br/> </xsl:template> </xsl:transform> generate-id() is first used to generate hotlinks containing each person's name then generate-id() is used to generate the targets for these hotlinks since generate-id() generates the same string every time it is applied to an individual node, the name and href attributes are guaranteed to match

30 Processing only distinct members of a node-set
Now that we know about both keys and the generate-id() function, we can ensure that, even in XSLT 1.0, we process only distinctly-valued members of a node-set In fact, what we do is we use an xsl:key element to split the node-set in question into subsets where all the nodes in some subset have the same value; then we use generate-id() to ensure that we process just the first member of each of these subsets

31 There were just four distinct key strings, fred rick geo and alf
Remember this example - we wanted to avoid manually listing each possible key string <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1" use="a"/> <xsl:template match="/"> <xsl:for-each select="/root/t1/a"> The target for <strong><xsl:value-of select="."/></strong> is <br/> <xsl:for-each select=" key('myKey', . ) "> <xsl:value-of select="."/> <br/> </xsl:for-each> <hr/> </xsl:template> </xsl:transform> There were just four distinct key strings, fred rick geo and alf But this stylesheet processed the fred string several times

32 A better stylesheet- which processes each key string just once
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" match="/root/t1/a" use="."/> <xsl:template match="/"> <xsl:for-each select="/root/t1/a[ generate-id(.)= generate-id(key('myKey',.)[position()=1]) ]"> The target for the key string <strong><xsl:value-of select="."/></strong> is <br/> <xsl:for-each select="key('myKey',.)"> <xsl:value-of select=".."/> <br/> </xsl:for-each> <hr/> </xsl:template> </xsl:transform> We apply the xsl:key over the range possible key strings, rather than over the t1 elements That is, we use <xsl:key name="myKey" match="/root/t1/a" use="."/> instead of <xsl:key name="myKey" match="/root/t1" use="a"/> We process an a element node only when it is the first member of the node set containing this key string

33 A more standard application of this approach
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="myKey" use="."/> <xsl:template match="/"> <xsl:for-each select=" generate-id(.) = generate-id(key('myKey',.)[position()=1])]"> The cities in <strong><xsl:value-of select="."/></strong> are <xsl:for-each select=" "> <xsl:value-of select="."/><xsl:text> </xsl:text> </xsl:for-each> <br/> </xsl:template> </xsl:transform> We use an xsl:key ranging over the country names We process a country node only when it is the first member of the target set for its key Then, we access all the country nodes in that target set, outputting for each one the value of the name attribute in its parent element

34 processing distinct values
Some more examples of processing distinct values

35 Consider this XML document
Example 1 <people> <person hair="red">Tom</person> <person hair="black">Dick</person> <person hair="white">Harry</person> <person hair="black">Mick</person> <person hair="red">Donal</person> </people> Consider this XML document Write a stylesheet which will, for each kind of hair, list the people with this hair That is, output this: The people with hair colour red are: Tom Donal  The people with hair colour black are: Dick Mick The people with hair colour white are: Harry

36 Thinking aloud Suppose we use
<people> <person hair="red">Tom</person> <person hair="black">Dick</person> <person hair="white">Harry</person> <person hair="black">Mick</person> <person hair="red">Donal</person> </people> Thinking aloud Suppose we use <xsl:for-each ... </xsl:for-each> That would process some hair colours too many times So we need to group the hair nodes into distinct sets, in which each set contains all nodes for the same hair colour Then we would process each hair node only if it were the first member of the set into which we had grouped it So we must use a set of keys like this <xsl:key name="myKey" use="."> Or, with a better name, <xsl:key name="colour" use=".">

37 Thinking aloud continued
If we have grouped the hair nodes into target sets like this <xsl:key name="colour" use="."> We can process the hair nodes with a loop like this <xsl:for-each provided it is the first member in its target set ]"> ... That is, we can process the hair nodes with a loop like this <xsl:for-each = generate-id(1st member in target set) ]"> ... That is, with a loop like this <xsl:for-each = generate-id( target set[position()=1] )]"> ... <xsl:for-each = generate-id( key('colour', . )[position()=1] )]">

38 Thinking aloud continued
So, our style-sheet will be like this <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="colour" use="."/> <xsl:template match="/"> <xsl:for-each = generate-id( key('colour', . )[position()=1] )]"> list the people with this hair </xsl:for-each> </xsl:template> </xsl:transform>

39 Thinking aloud continued
So, our style-sheet will be like this <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="colour" use="."/> <xsl:template match="/"> <xsl:for-each = generate-id( key('colour', . )[position()=1] )]"> The people with hair colour <xsl:value-of select="."/> are: <xsl:for-each select=" the set of people with this hair colour "> <xsl:value-of select="."/><xsl:text> </xsl:text> </xsl:for-each> <br/> </xsl:template> </xsl:transform>

40 The final stylesheet So, our style-sheet will be like this
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="colour" use="."/> <xsl:template match="/"> <xsl:for-each = generate-id( key('colour', . )[position()=1] )]"> The people with hair colour <xsl:value-of select="."/> are: <xsl:for-each select=" key('colour', .}/.. "> <xsl:value-of select="."/><xsl:text> </xsl:text> </xsl:for-each> <br/> </xsl:template> </xsl:transform>

41 Consider this XML document
Example 2 <recordings> <recording> <artist>The Beatles</artist> <song>Hello</song> </recording> <artist>Bob Dylan</artist> <song>Goodbye</song> <artist>Rod Stewart</artist> </recordings> Consider this XML document Write a stylesheet which will, for each song, list the people who have recorded it That is, output this: The people who have recorded Hello are: The Beatles, Bob Dylan The people who have recorded Goodbye are: Bob Dylan, Rod Stewart

42 Thinking aloud Suppose we use
<recordings> <recording> <artist>The Beatles</artist> <song>Hello</song> </recording> ... </recordings> Thinking aloud Suppose we use <xsl:for-each select="//recording/song"> ... </xsl:for-each> That would process the songs too many times So we need to group the songs into distinct sets, in which each set contains all nodes for the same song Then we would process each song node only if it were the first member of the set into which we had grouped it So we must use a set of keys like this <xsl:key name="myKey" match="//recording/song" use="."> Or, with a better name, <xsl:key name="title" match="//recording/song" use=".">

43 Thinking aloud continued
If we have grouped the song nodes into target sets like this <xsl:key name="title" match="//recording/song" use="."> We can process the song nodes with a loop like this <xsl:for-each select="//recording/song[ provided it is the first member in its target set ]"> ... That is, we can process the song nodes with a loop like this <xsl:for-each select="//recording/song[generate-id(.) = generate-id(1st member in target set) ]"> ... That is, with a loop like this <xsl:for-each select="//recording/song[generate-id(.) = generate-id( target set[position()=1] )]"> ... <xsl:for-each select="//recording/song[generate-id(.) = generate-id( key('title', . )[position()=1] )]">

44 Thinking aloud continued
So, our style-sheet will be like this <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="title" match="//recording/song" use="."/> <xsl:template match="/"> <xsl:for-each select="//recording/song[generate-id(.) = generate-id( key('title', . )[position()=1] )]"> list the artists who recorded this song </xsl:for-each> </xsl:template> </xsl:transform>

45 Thinking aloud continued
So, our style-sheet will be like this <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="title" match="//recording/song" use="."/> <xsl:template match="/"> <xsl:for-each select="//recording/song[generate-id(.) = generate-id( key('title', . )[position()=1] )]"> The people who have recorded <xsl:value-of select="."/> are: <xsl:for-each select=" the set of people who recorded this song "> <xsl:value-of select="."/> if this artist is not the last, output a comma and a space </xsl:for-each> <br/> </xsl:template> </xsl:transform>

46 Thinking aloud continued
So, our style-sheet will be like this <?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="title" match="//recording/song" use="."/> <xsl:template match="/"> <xsl:for-each select="//recording/song[generate-id(.) = generate-id( key('title', . )[position()=1] )]"> The people who have recorded <xsl:value-of select="."/> are: <xsl:for-each select=" the set of people who recorded this song "> <xsl:value-of select="."/> <xsl:if test="position() < last()"><xsl:text>, </xsl:text></xsl:if> </xsl:for-each> <br/> </xsl:template> </xsl:transform>

47 The final stylesheet So, our style-sheet will be like this
<?xml version="1.0"?> <xsl:transform xmlns:xsl=" version="1.0" > <xsl:output method="html" /> <xsl:key name="title" match="//recording/song" use="."/> <xsl:template match="/"> <xsl:for-each select="//recording/song[generate-id(.) = generate-id( key('title', . )[position()=1] )]"> The people who have recorded <xsl:value-of select="."/> are: <xsl:for-each select=" key('title',.)/../artist "> <xsl:value-of select="."/> <xsl:if test="position() < last()"><xsl:text>, </xsl:text></xsl:if> </xsl:for-each> <br/> </xsl:template> </xsl:transform>


Download ppt "Lecture 21."

Similar presentations


Ads by Google