Subject: Re: "Skip until"?? From: Jeni Tennison <jeni.tennison@xxxxxxxxxxxxxxxx> Date: Tue, 08 Aug 2000 10:45:45 +0100 |
Heiner, >Now, my XSLT file should be like this: > >1. Match all <node> elements >2. If element contains "name:", "subject:" or "date:", then continue >processing >3. If element contains the unwanted name "Jones" then: >3a. Skip until element contains "name:" again >3b. Process 3 again >4. Show value of element Are you sure you *really* need to go about it in this way? The way you're thinking here is very procedural: you're trying to process each node in turn and use the results of processing this node to determine which nodes to process next. This is causing you problems because XSLT is much better suited for declarative solutions to problems. This is really a grouping problem: you want to output all the information about a particular person (unless they are 'Jones'). So I'd first create groups of nodes for each person using xsl:key: <xsl:key name="people" match="node" use="(self::node | preceding-sibling::node)[starts-with(., 'name:')][last()]" /> Just to explain the use expression here. This is searching for the node that holds the 'name' for the group. This can be either the node itself or one of its preceding siblings. Of course, the further down the file you get, the more preceding siblings there are that have names (for example, Miller's subject: node has the names 'Miller', 'Jones' and 'Smith' to choose from). You want the last of these (the most recent). [Aside: note that this is [last()] rather than [1] because the braces around the node set (self::node | preceding-sibling::node) mean that the node set gets given in document order rather than reverse document order.] You can then process only those nodes that start with 'name:', secure in the knowledge that you can get the rest of the nodes using the key. You can also filter out any nodes that you want. Basically, you're only processing the first node in each group - in this particular case it's easy to identify which those are because their content starts with 'name:'. <xsl:template match="root"> <xsl:apply-templates select="node[starts-with(., 'name:') and substring-after(., ' ') != 'Jones']" mode="process-group" /> </xsl:template> The following template then matches on 'node' in the 'process-group' mode. You don't have to worry about selecting which nodes to process here: you've selected them in the calling template (above), so you can guarantee that the only nodes that reach this template are going to be the ones you're interested in. The template uses the key to get the other nodes relevant to the person and applies templates to them. <xsl:template match="node" mode="process-group"> ---- <xsl:for-each select="key('people', .)"><xsl:text> </xsl:text> <xsl:apply-templates select="." /> </xsl:for-each> </xsl:template> You could definitely solve this problem without using keys, but I think the select expression in the for-each would be really hideous (mind you, the use expression in the xsl:key is nothing to write home about). 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 -> |
---|---|---|
"Skip until"??, Heiner de Wendt | Thread | RE: "Skip until"??, Kay Michael |
Re: SAX is not XML (Key() Re: Saxon, Sebastian Rahtz | Date | Re: Bug in 'xsl:sort'. ( XT vs SAXO, James Clark |
Month |