Re: [xsl] what to do if id() doesn't recognize xml:id

Subject: Re: [xsl] what to do if id() doesn't recognize xml:id
From: Michael Kay <mike@xxxxxxxxxxxx>
Date: Fri, 14 Jan 2011 10:35:05 +0000
On 14/01/2011 09:55, TW wrote:
I'm currently fathoming what's possible with keys as they are really
quite handy.  I'm not sure yet whether I fully understand how they
work.  In a short flash of excitement I thought I could do something
like the following:  If I have data like this

<?xml version="1.0"?>
<?xml-stylesheet type='text/xsl' href='xsl/musx2svg.xsl'?>
<children>
   <mother xml:id="mother1" name="Laura">
     <child father="father1" name="Kim"/>
     <child father="father2" name="Peter" />
   </mother>
   <mother xml:id="mother2" name="Sarah">
     <child name="Ron" father="father2" />
   </mother>
   <father xml:id="father1" name="Jim">
     <child mother="mother1"/>
   </father>
   <father name="George"/>
</children>

where children can either be stored as child elements of their mothers
or fathers, I could maybe directly select the mother of the current
<child>  element like "key('mother',.)" regardless of how they are
stored if I was using a key like

<xsl:key name="mother" match="mother" use="child|//child[@mother =
current()/@xml:id]"/>
Well, for starters, it's a pretty strange way of representing your data.

But I think you're making it too complicated. Define a simple key

<xsl:key name="id" match="*" use="xml:id"/>

and then a function

<xsl:function name="mother" as="element(mother)*">
<xsl:param name="child" as="element(child)"/>
<xsl:sequence select="$child/parent::mother | key('id', $child/@mother)"/>
</xsl:function>

Michael Kay
Saxonica

But then I realized that not the nodes themselves from the node-set
that's returned by "child|//child[@mother = current()/@xml:id]" would
work as keys, but their string values would.  Unfortunately something
like "generate-id(child|//child[@mother = current()/@xml:id])" would
of course destroy the effect as only for for the first element of the
node-set a key would be generated.

So I figured I could add IDs to all<child>  elements in an additional
processing step and use a key like

<xsl:key name="mother" match="mother"
use="child/@xml:id|//child[@mother = current()/@xml:id]/@xml:id"/>

But there are potential problems if there

(Of course in this made up example one could as well use
"(parent::mother|key('id',@mother))".  However my intent is not to
solve a special example case.  I'd like to get a clearer idea of where
keys are applicable and where they aren't.)

Thomas W.

Current Thread