Subject: Re: [xsl] Define internal xsl variable From: Mukul Gandhi <gandhi.mukul@xxxxxxxxx> Date: Fri, 7 Oct 2011 20:02:46 +0530 |
I played with little bit of schema awareness for this use case, and here's what I came up with, (this is essentially produced with Mike's idea to have recursive processing of your input. I've used a recursive named template, where's Mike suggested to use sibling recursion -- which is actually elegant, but conceptually both achieve same objectives) Firstly, I could analyze why we need recursion for this problem. Essentially because, your further output depends on the output generated so far. With these thoughts, here's a solution simulating your problem, Input XML document: <X xmlns="http://www.example.org/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/test foo.xsd"> <cell>foo</cell> <cell span="2">bar</cell> <cell span="3">baz</cell> <cell>test</cell> </X> The XSD schema I use for schema aware system (named foo.xsd): <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/test" xmlns:t="http://www.example.org/test"> <xs:element name="X"> <xs:complexType> <xs:sequence> <xs:element ref="t:cell" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="cell"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="span" type="xs:integer"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:schema> The XSLT 2.0 stylesheet: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="http://www.example.org/test" exclude-result-prefixes="xs" version="2.0"> <xsl:output method="xml" indent="yes"/> <xsl:import-schema namespace="http://www.example.org/test" schema-location="foo.xsd"/> <xsl:template match="t:X"> <result> <xsl:call-template name="transformInputStruct"> <xsl:with-param name="refNodePos" select="1" as="xs:integer"/> <xsl:with-param name="resltList" select="1" as="xs:integer*"/> </xsl:call-template> </result> </xsl:template> <xsl:template name="transformInputStruct"> <xsl:param name="refNodePos" as="xs:integer"/> <xsl:param name="resltList" as="xs:integer*"/> <t:data><xsl:value-of select="$resltList"/></t:data> <xsl:variable name="nxtNode" select="t:cell[$refNodePos + 1]"/> <xsl:if test="$nxtNode"> <xsl:variable name="previousValue" select="max($resltList)"/> <xsl:variable name="maxValue" select="if ($nxtNode/@span) then ($previousValue + 1 + $nxtNode/@span) else ($previousValue + 1)"/> <xsl:call-template name="transformInputStruct"> <xsl:with-param name="refNodePos" select="$refNodePos + 1" as="xs:integer"/> <xsl:with-param name="resltList" select="for $num in ($previousValue + 1) to $maxValue return $num" as="xs:integer*"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet> When I transform the input document specified above, with the stylesheet above, I get output: (the element "result" is a wrapper for your desired result element sequence -- I wanted to make the output XML document well-formed) <?xml version="1.0" encoding="UTF-8"?> <result xmlns:t="http://www.example.org/test"> <t:data>1</t:data> <t:data>2 3 4</t:data> <t:data>5 6 7 8</t:data> <t:data>9</t:data> </result> I wrote this schema aware solution, to avoid explicit casts in XPath expressions. To use something like this, invocation of XSLT 2.0 transform must be preceded by an XSD validation of input document. We could easily have written an untyped version of this solution (i.e without the schema), but then I would have found it uglier (!) with the XPath expressions that I might have written for such a solution, and have lost other benefits of a strongly typed data. I'm also not suggesting, to over complicate the solution with unnecessary semantics (i.e schema awareness in this case). But this solution was just food for some thought :) On Wed, Oct 5, 2011 at 1:31 PM, Susanne Wunsch <xsl@xxxxxxxxxxxxxxxxx> wrote: > Hello, > > I'm Susanne and did already some xsl transformations before. For now I try > to define an internal xsl variable but the xpath expression doesn't work > so far. > > (The current xsl approach is shown below.) > > The 'origin' variable should be mapped into the following node set (in the > 'spannedCells' variable): > > <t:data>1</t:data> > <t:data>2 3</t:data> > <t:data>4 5 6</t:data> > <t:data>7</t:data> > > It shows occupied cells including the "spanned" ones. I think that some > recursive design should be possible but I just didn't find how to start in > this case. > > I would be very glad about any hint. > > Full xsl file follows: > ------------------------------------------------------------------------- > <?xml version="1.0" encoding="UTF-8"?> > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > B xmlns:xs="http://www.w3.org/2001/XMLSchema" > B xmlns:t="http://www.example.org/test" > B version="2.0"> > > B <xsl:template name="main"> > B B <xsl:variable name="origin" as="node()*"> > B B B <t:cell>foo</t:cell> > B B B <t:cell span="2">bar</t:cell> > B B B <t:cell span="3">baz</t:cell> > B B B <t:cell>test</t:cell> > B B </xsl:variable> > > B B <xsl:variable name="SpannedCells" as="node()*"> > B B B <t:data>1</t:data> > B B B <xsl:for-each select="$origin[position() > 1]"> > B B B B <xsl:variable name="PreviousValue" > B B B B B select="xs:integer(max(preceding::t:data/text()))"/> > B B B B <xsl:variable name="MaxValue" > B B B B B select="if (./@span) then ($PreviousValue + 1 + @span) > B B B B B else ($PreviousValue + 1)"/> > B B B B <t:data> > B B B B B <xsl:value-of select="($PreviousValue + 1) to $MaxValue"/> > B B B B </t:data> > B B B </xsl:for-each> > B B </xsl:variable> > > B B <xsl:message select="$SpannedCells"/> > B </xsl:template> > </xsl:stylesheet> > ------------------------------------------------------------------------ > > Thanks and kind regards... > Susanne -- Regards, Mukul Gandhi
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Define internal xsl varia, Michael Kay | Thread | [xsl] Unable to select wanted nodes, Mark |
Re: [xsl] how to remove the duplica, team wise | Date | Re: [xsl] Unable to select wanted n, Mark |
Month |