Re: Keys on multiple element types
Hi Ahmad, > q1. Whats wrong with the stylesheet that it doesnt do this. I think its :- > select="RECORDA[generate-id(. > > but every other path I try ends up with no output. You're correct that it's that part of the stylesheet that's causing the problem. The problem is that you're selecting only the RECORDA elements, but you're interested in the RECORDB and RECORDC elements as well. One method would be to select the unique ones from all three types as follows: (RECORDA | RECORDB | RECORDC) [generate-id(.) = generate-id(key('rows', name))] Or you could just select all the element children of the current FILES element, and filter to select only those that appear first in the document with a particular name, as follows: *[generate-id(.) = generate-id(key('rows', name))] If you didn't want to list all the RECORD names, you could do a similar thing with the definition of the key - make it match those elements that are children of the FILES element, no matter what their name is: <xsl:key name="rows" match="FILES/*" use="name" /> > q2. Does the vertical bar | mean 'or', and wouldnt it be better to > use ',' which I think means 'and'? When I tried ',' it threw up > loads of exceptions. In an expression, the vertical bar (|) means 'union'. In the example above, (RECORDA | RECORDB | RECORDC) creates a union of the nodes that you select with the individual expressions RECORDA, RECORDB and RECORDC, so you get all RECORDA, RECORDB and RECORDC elements. In a pattern (a match attribute), the vertical bar gives alternative patterns. So the pattern RECORDA | RECORDB | RECORDC matches RECORDA, RECORDB and RECORDC elements. The comma (,) isn't an operator in XPath 1.0 (it's only used to separate arguments in a function call). You might have been confused by recent discussions on this list, because the comma *is* an operator in XPath 2.0 (at least in the current WDs), where it's used to construct a sequence. In XPath 2.0, if you do (RECORDA | RECORDB | RECORDC) then you get the RECORDA, RECORDB and RECORDC elements in whatever order they appear. If you do (RECORDA, RECORDB, RECORDC) then you get all the RECORDA elements followed by all the RECORDB elements followed by all the RECORDC elements. But this doesn't apply in XPath 1.0 (and XSLT 1.0). To do 'or', use the operator 'or' (e.g. name = 'foo' or name = 'bar'). To do 'and', use the operator 'and' (e.g. name = 'foo' and name = 'bar'). > q.3 If the xml looked like this instead... > > <FILES> > <RECORDA> > <id>13</id><name>Fred</name><project_name>Building</project_name> > </RECORDA> > <RECORDA> > <id>14</id><name>Fred</name><project_name>Building</project_name> > </RECORDA> > <RECORDB> > <id>15</id><name>Fred</name><project_name>Looking</project_name> > </RECORDB> > <RECORDC> > <id>16</id><name>Harry</name><project_name>Writing</project_name> > </RECORDC> > </FILES> > > How could I get the result to remove multiple copies e.g. to output > <id>13</id> but not <id>14</id> I'm not sure what a 'multiple copy' is in the above. Should the RECORDB with id 15 be output or not? If so, you need to define a key that indexes the records on both the name of the element (e.g. 'RECORDA', 'RECORDB' or 'RECORDC') and the name element child (e.g. 'Fred' or 'Harry'). That kind of key might look like: <xsl:key name="rows" match="FILES/*" use="concat(name(), '+', name)" /> Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
PURCHASE STYLUS STUDIO ONLINE TODAY!
Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!
Download The World's Best XML IDE!
Accelerate XML development with our award-winning XML IDE - Download a free trial today!
Subscribe in XML format