Subject: Re: xsl:key From: Jeni Tennison <Jeni.Tennison@xxxxxxxxxxxxxxxx> Date: Thu, 22 Jun 2000 11:16:56 +0100 |
Hi Rhonda, >My aim is to extract paragraphs from the source tree >(temp.xml) to be output to a result tree according to >two criteria: > > * Target doc="contract" and > * Target host="true" > >This is an extension of my original question. >The output I receive is all paragraphs disregardless >of attribute doc and host values. I have attempted >to achieve my goal using two methods. I hope that you/other >might be able to assist me. You're really close with both your methods, but I think that you need to have a look at XPath and how to put XPath expressions together, because that's where many of your problems lie. >ATTEMPT 1: Using the Key() function >============================= > >I realise that only one key value can be used and >then the other key value can be used on the filtered >result - unless the intersection saxon extension >function is used. That's true, but you can make keys that combine two values, using concat(). So, we can index on a string like 'contract-true' using: <xsl:key name="blueprint" match="Para" use="concat(ancestor::Target/@doc, '-', ancestor::Target/@host)" /> Note that now that you've changed the way your input is structured, what you're after are the 'doc' and 'host' attributes of the Target ancestors of the particular Para, not a sibling. >However here I still receive >all paragraphs, it seems without referencing >the index created by my xsl:key? Have a look at your template: ><xsl:template match="Para"> > <xsl:element name="{name()}"> > <xsl:copy-of select="key('blueprint', contract)"/> > <xsl:apply-templates/> > </xsl:element> ></xsl:template> You're matching all 'Para' elements, and then (for all of them), creating an element called 'Para'. Within that element, you're putting a copy of the node set that you get when you retrieve the nodes from the 'blueprint' key, using the value of the 'contract' element as the key. This is far from what you want to do. What you want to do is select all the Para elements that are in the list that is retrieved when you use the key 'contract-true' on the 'blueprint' key, and process only them, making a copy of them. When you only want to process a subset of nodes, then you should only apply templates to that subset, which means changing your root-node matching template: <xsl:template match="/"> <xsl:apply-templates select="key('blueprint', 'contract-true')" /> </xsl:template> <xsl:template match="Para"> <xsl:copy-of select="." /> </xsl:template> I'm not sure what exactly you want your output to look like: this just copies the relevant 'Para' elements: you might want to wrap them in another element, in which case you should put it in the root-node matching template. >I have also, since simply typed the value of contract >in the key, quotes do not seem to make any difference >either way. They do make a difference in how it's interpreted, just not in your overall result because either way it wasn't working! :) When you put 'contract' in quotes, it interprets it as the string 'contract', which is what you want. When you don't put it in quotes, it interprets it as an XPath expression, and tries to find a child element of the current node that is called 'contract', and use its content as the value to index into the key. >ATTEMPT 2: Using a template match >============================ > >*** the following template is never used *** >*** and I did hope that this template would *** >*** select paragraphs according to attrib values *** >*** specified? *** > ><xsl:template match='Para/Target[@doc="contract" > and @host="true"]'> > <xsl:element name="{name()}"> > <xsl:copy-of select="attribute::node()"/> > <xsl:apply-templates/> > </xsl:element> ></xsl:template> You need to change the XPath expression that you're using here. Let me explain what the XPath you're using says: Para/Target[@doc="contract" and @host="true"] Find an element called 'Target' that has a parent element called 'Para' and has a 'doc' attribute with a value of 'contract' and has a 'host' attribute with a value of 'true' There are no such Paras in your input. What you want to say is: Find an element called 'Para' that has an ancestor element called 'Target' that has a 'doc' attribute with a value of 'contract' and has an ancestor element called 'Target' that has a 'host' attribute with a value of 'true' This can be expressed as: Para[ancestor::Target[@doc="contract"] and ancestor::Target[@host="true"]] or Target[@doc="contract"]//Para[ancestor::Target[@host="true"]] or Target[@host="true"]//Para[ancestor::Target[@doc="contract"]] Given your current input, a better version (because it involves less hunting around for matching nodes) is: Find an element called 'Para' that has a parent element called 'Target' that has a 'host' attribute with a value of 'true' and has a grandparent element called 'Target' that has a 'doc' attribute with a value of 'contract' This can be expressed as: Target[@doc="contract"]/Target[@host="true"]/Para You should also make sure that you *only* process those 'Para' elements, because the XSLT Processor has built-in templates that match other elements and will output their textual content. Again, this means putting your XPath expression higher up in your templates: make sure that you then adapt it according to the current node within the template you put it in. For example: <xsl:template match="/"> <xsl:apply-templates select="//Para[ancestor::Target[@doc='contract'] and ancestor::Target[@host='true']]" /> </xsl:template> or <xsl:template match="Template"> <xsl:apply-templates select="Target[@doc="contract"]/Target[@host="true"]/Para" /> </xsl:template> I hope that 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 -> |
---|---|---|
xsl:key, Rhonda Fischer | Thread | optional attributes, Lisa van Gelder |
calling template from FORM action, Mats Norreby | Date | RE: How is this part of the XSLT sp, Thorbjørn Ravn Ander |
Month |