Subject: Re: Creating different types of output From: Jeni Tennison <Jeni.Tennison@xxxxxxxxxxxxxxxx> Date: Tue, 20 Jun 2000 20:02:58 +0100 |
Laurie, >I would also like to create annual listings from the same source, >and I didn't think it would be all that hard. However, >it seems to require more programming >skills than I have (which are close-to-none). > >The source file has all the years coded in the XML file. When I run >my "build year" script, I get one HTML file for each year. However, I >only get one record for each year, and that record is always the last >alphabetical listing for that year. So what seems to be happening >is that each time a new year is encountered, the year output file is >completely >overwritten, rather than the new record being appended to the >existing output file. The problem with the stylesheet that you gave is that it matches on each individual dpsrecord, and each time it matches, it creates a file for that particular dpsrecord. You are right that the output file is being overwritten because there are several dpsrecords with the same year. Overwriting is sensible behaviour - it is difficult to append to XML files because they have to be well-formed, which means it's not as simple as just adding elements to the end of a file. I'm not sure from your example whether your file is ordered by year of death already, but I assume that it's not, that it's ordered by surname instead, and that the 'dpsletter' elements hold dpsrecords for people whose surnames start with the same letter. Your overall problem is a grouping problem as well as an output problem. You want to group all the 'dpsrecord' elements that have the same deathdate/year together in the same output file. When I see a grouping problem I immediately think of keys, because keys allow you to group elements together according to some characteristic of the element, in this case the deathdate. The first thing I would do is to identify which dpsrecords should be grouped together, and define a key. When you define a key, using the xsl:key element, there are three attributes: * name: the name of the key, can be anything you like (in your case 'records', say) * match: the type of nodes that need to be grouped together (in your case 'dpsrecord' elements) * use: the thing that you group on, as an XPath from a matched node (in your case the value of deathrate/year) This gives a key of: <xsl:key name="records" match="dpsrecord" use="deathdate/year" /> Defining a key like this enables you to get a list of all the dpsrecords from a particular year (ordered in the same order as they appear in your input) by using the 'key' function. So, for example: key('records', '1993') would give you a node list of all the dpsrecords in which the dead person died in 1993, in alphabetical order by surname. You want to create a new document for each of those sets of dpsrecords. The standard way of doing this consists of two parts: 1. identifying the first dpsrecord in the set 2. creating output for all the dpsrecords in that set You have to go through this two-stage process because you usually don't know in advance what the keys are that are used to identify the groups. In your case you could do it by stepping through a year at a time, because the keys you're using are numerical and you could provide information about the earliest and latest year in your file. I'm not going to show you that approach, though, firstly because it's not as general, and secondly because it would, by design, involve you updating your stylesheet each year, which isn't good maintenance practice. Identifying the first dpsrecord in a set involves testing to see whether a particular dpsrecord that you know about is the same as the first dpsrecord you get when you retrieve the list of dpsrecords with the same death year. You should probably use generate-id() to test whether two nodes are equivalent. An XPath expression that generates all dpsrecords that are first in their death-year group is: /set/dpsletter/dpsrecord[generate-id() = generate-id(key('records', deathdate/year)[1])] You should make sure that you are only processing those dpsrecords, by selecting them when you apply-templates (presumably within the 'set'-matching template) e.g.: <xsl:template match="set"> ... <xsl:apply-templates select="dpsletter/dpsrecord[generate-id() = generate-id(key('records', deathdate/year)[1])]" /> ... </xsl:template> Now you can guarantee that your dpsrecord-matching template is only matched once for each death year. That means that within it you can generate all the output you want in a particular file, without worrying about it being overwritten. This should include iterating over the dpsrecords from that particular death year, adding their information into the file, using xsl:for-each. So: <xsl:template match="dpsrecord"> <xsl:variable name="filename"> <xsl:value-of select="deathdate/year"/> </xsl:variable> <xt:document href="{concat($filename,'.shtml')}"> <html> <head> <title>Dead People Server - People Who Died in the Year <xsl:value-of select="deathdate/year"/></title> <LINK REL="stylesheet" HREF="dps.css" TYPE="text/css" /> </head> <body> <xsl:for-each select="key('records', $filename)"> <ul> <xsl:apply-templates /> </ul> </xsl:for-each> </body> </html> </xt:document> </xsl:template> A couple of comments: I've used $filename rather than deathdate/year in the key() function because you've already retrieved that information, so you may as well reuse it. Also, if you want to have another 'dpsrecord'-matching template that produces the information for that dpsrecord, rather than generating a page, then you could use modes to distinguish between them. This has been tested and works in SAXON, albeit using the extension function with the equivalent functionality to xt:document, and not having a full set of dpsrecords to play with. I hope this helps, Jeni Dr Jeni Tennison Epistemics Ltd, Strelley Hall, Nottingham, NG8 6PE Telephone 0115 9061301 ? Fax 0115 9061304 ? Email jeni.tennison@xxxxxxxxxxxxxxxx XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: Creating different types of out, Alan Houser | Thread | Antw: The XSL-List Digest V3 #70 (U, Anita Fend |
Outputing an '&' from XSL, Warren Hedley | Date | Re: How is this part of the XSLT sp, Warren Hedley |
Month |