Subject: Re: [xsl] A little cross referencing problem From: Joerg Pietschmann <joerg.pietschmann@xxxxxx> Date: Wed, 22 Aug 2001 17:29:55 +0200 |
"Pywell, Andrew" <Andrew.Pywell@xxxxxxxxxx> wrote: > I have a little cross-referencing problem. My XML looks like this > > <?xml version="1.0"?> > <messageData> > <message dir="0" key="234" text="bla bla"/> > <message dir="1" key="235" text="more bla bla"/> [snip] > <in key="240" status="File Error"/> > <in key="241" status="No Error"/> > <out key="235" status="No Error"/> > <out key="237" status="No Error"/> > </messageData> [snip] > > If dir="0" then I need to find the matching "key" in <in> and extract the > value of "status". Similarly if dir="1" the I need the "status" of the > matching <out> record > There are several solutions. One is to use xsl:choose to discriminate whether the direction ist "In" or "Out": <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="ISO-8859-1"/> <xsl:strip-space elements="*"/> <xsl:template match="message"> <xsl:choose> <xsl:when test="@dir=0"> <xsl:text>In </xsl:text> <xsl:value-of select="/*/in[@key=current()/@key]/@status"/> </xsl:when> <xsl:when test="@dir=1"> <xsl:text>Out </xsl:text> <xsl:value-of select="/*/out[@key=current()/@key]/@status"/> </xsl:when> <xsl:otherwise> <xsl:message terminate="yes">Error in data</xsl:message> </xsl:otherwise> </xsl:choose> <xsl:text> </xsl:text> <xsl:value-of select="@text"/> <xsl:text>
</xsl:text> </xsl:template> </xsl:stylesheet> Not that the code above will complain if the key attribute of a message is illegal, but will not notice if there are no or more than one matching in/out elements. You can have more fun with keys, and perhaps some performance gain: <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="ISO-8859-1"/> <xsl:strip-space elements="*"/> <xsl:key name="in" match="in" use="@key"/> <xsl:key name="out" match="out" use="@key"/> <xsl:template match="message"> <xsl:choose> <xsl:when test="@dir=0"> <xsl:text>In </xsl:text> <xsl:value-of select="key('in',@key)/@status"/> </xsl:when> <xsl:when test="@dir=1"> <xsl:text>Out </xsl:text> <xsl:value-of select="key('out',@key)/@status"/> </xsl:when> <xsl:otherwise> <xsl:message terminate="yes">Error in data</xsl:message> </xsl:otherwise> </xsl:choose> <xsl:text> </xsl:text> <xsl:value-of select="@text"/> <xsl:text>
</xsl:text> </xsl:template> </xsl:stylesheet> Now for even more fun and some obfuscation, you can select the key dynamically <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="ISO-8859-1"/> <xsl:strip-space elements="*"/> <xsl:key name="k0" match="in" use="@key"/> <xsl:key name="k1" match="out" use="@key"/> <xsl:template match="message"> <xsl:apply-templates select="key(concat('k',@dir),@key)"/> <xsl:text> </xsl:text> <xsl:value-of select="@text"/> <xsl:text>
</xsl:text> </xsl:template> <xsl:template match="in"> <xsl:text>In </xsl:text> <xsl:value-of select="@status"/> </xsl:template> <xsl:template match="out"> <xsl:text>Out </xsl:text> <xsl:value-of select="@status"/> </xsl:template> <xsl:template match="/"> <xsl:apply-templates select="*/message"/> </xsl:template> </xsl:stylesheet> Think about why there is suddenly a template matching "/" necessary. The code above will get a nasty runtime error if a dir attribute contains an illegal value. This leads to my favorite piece of code which guards the invocation of the dynamically selected key by having a key lookup in the stylesheet whether the key actually exists. <xsl:key name="key" match="xsl:key" use="@name"/> <xsl:template match="message"> <xsl:variable name="key" select="concat('k',@dir)"/> <xsl:choose> <xsl:when test="document('')[key('key',$key)]"> <xsl:apply-templates select="key($key,@key)"/> </xsl:when> <xsl:otherwise> <xsl:message terminate="yes">Error in data</xsl:message> </xsl:otherwise> </xsl:choose> <xsl:text> </xsl:text> <xsl:value-of select="@text"/> <xsl:text>
</xsl:text> </xsl:template> I hope you didn't get an overdose of keys by now :-) Have fun! J.Pietschmann XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] A little cross referencin, Pywell, Andrew | Thread | Re: [xsl] A little cross referencin, Jeni Tennison |
[xsl] XMLDOM xml to html translatio, Joseph Coffman | Date | RE: [xsl] XMLDOM xml to html transl, Chris Bayes |
Month |