Subject: Re: [xsl] character entities From: Joerg Pietschmann <joerg.pietschmann@xxxxxx> Date: Wed, 28 Nov 2001 12:37:25 +0100 |
Dimitre Novatchev <dnovatchev@xxxxxxxxx> wrote: > > > Also I'd have to go outside XSLT 1.0 ... then there is _nothing_ a > > > template can do to create that node set, as templates don't create > > > nodesets. > I didn't "jump onto this", because generic templates cannot help here -- they > create/return RTFs, which even when transformed to a nodeset do not contain the > original nodes but their copies. I rather thougt of using the equivalent of a function pointer. For illustration: 1. Foo-elements as previous sibling in document (perhaps included there as entity) <xsl:template ... > ... <xsl:for-each select="previous-sibling::foo[1]/bar"> <!-- do stuff --> ... 2. Foo-elements perhaps in external document, use copy-of and node-set <xsl:template ... > ... <xsl:variable name="stuff"> <xsl:choose> <xsl:when test="previous-sibling::*[1][self::nag:reference]"> <xsl:copy-of select="document(previous-sibling::nag:reference[1]/@url)/refitem/foo)"/> </xsl:when> <xsl:when test="previous-sibling::*[1][self::foo]"> <xsl:copy-of select="previous-sibling::self::foo"/> </xsl:when> <xsl:otherwise> <xsl:message terminate="yes">Problem getting foo</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:for-each select="xx:node-set($stuff)/bar"> <!-- do stuff --> ... Obvious disadvantage: the processing stage cannot refer to ancestors and siblings of foo-elements. 3. Foo-elements perhaps referenced, use indirection for xpaths crossing the reference boundaries. <i:do-stuff/> <xsl:template match="i:do-stuff"> <xsl:param name="reference-node"/> <xsl:param name="stuff"/> <!-- do stuff --> </xsl:template> <xsl:template name="get-foo"> <xsl:param name="f"/> <xsl:choose> <xsl:when test="previous-sibling::*[1][self::nag:reference]"> <xsl:apply-template select="$f"> <xsl:with-param name="reference-node" select="previous-sibling::nag:reference[1]"/> <xsl:with-param name="stuff" select="document(previous-sibling::nag:reference[1]/@url)/refitem/foo)"/> </xsl:apply-template> </xsl:when> <xsl:when test="previous-sibling::*[1][self::foo]"> <xsl:apply-template select="$f"> <!-- leave reference-node empty --> <xsl:with-param name="stuff" select="previous-sibling::self::foo"/> </xsl:apply-template> </xsl:when> <xsl:otherwise> <xsl:message terminate="yes">Problem getting foo</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> ... <xsl:template ... > ... <xsl:call-template name="get-foo"> <xsl:with-param name="f" select="document('')/*/i:do-stuff"/> </xsl:call-template> You can use the get-foo template everywhere where you have to gather foos and pass the actual function to be invoked on the foos as a parameter. I'm not quite sure whether this is actually a "generic template", until recently i thought so. Moreover, in order to reference arbitrary ancestors and siblings from the conceptual tree, some other templates have to be used <xsl:template name="get-previous-sibling-foo"> <xsl:param name="reference-node"/> <xsl:param name="context"/> <xsl:param name="f"/> <xsl:choose> <xsl:when test="$reference-node"> <xsl:apply-templates select="$f"> <xsl:with-param name="reference-node" select="$reference-node"/> <xsl:with-param name="stuff" select="$reference-node/previous-sibling::foo"/> <xsl:with-param name="context" select="$context"/> </xsl:apply-templates> <xsl:when> <xsl:otherwise> <xsl:apply-templates select="$f"> <xsl:with-param name="reference-node" select="$reference-node"/> <xsl:with-param name="stuff" select="$context/previous-sibling::foo"/> <xsl:with-param name="context" select="$context"/> </xsl:apply-templates> </xsl:otherwise> </xsl:choose> </xsl:template> and something similar for ancestors and everything else. hardcoding all the element names ("foo") into all the templates above may not be desirable. A xx:evaluate() extension could be used, or a somewhat crude interpreter of an xml-ified xpath-syntax: <xsl:template name="evaluate-simple-xpath"> <xsl:param name="xpath"/> <xsl:param name="reference-node"/> <xsl:param name="context"/> <xsl:param name="result"/> <xsl:param name="f"/> <xsl:choose> <xsl:when test="not($xpath)"> <!-- end condition for recursion: xpath empty, invoke function --> <xsl:apply-templates select="$f"> <xsl:with-param name="reference-node" select="$reference-node"/> <xsl:with-param name="stuff" select="$result"/> <xsl:with-param name="context" select="$context"/> </xsl:apply-templates> </xsl:when> <xsl:when test="$xpath/step/axis='previous-sibling'"> <xsl:choose> <xsl:when test="generate-id($result)=generate-id($reference-node)"> <!-- we are crossing the reference boundary --> <xsl:call-template name="evaluate-predicate"> <xsl:param name="$xpath/predicate"/> <xsl:with-param name="reference-node" select="$reference-node"/> <xsl:with-param name="result" select="$reference-node/previous-sibling::*[name()=$xpath/step/name"/> <xsl:with-param name="context" select="$context"/> <xsl:with-param name="f" select="$f"/> </xsl:call-template> <xsl:when> <!-- other cases --> </xsl:when> <!-- other axes --> </xsl:choose> </xsl:template> I'm afraid the above won't work, especially as it's probably possible to encounter other references, but i hope you'll get the general picture. Invoke this like <x:foo-path> <step> <axis>previous-sibling</axis> <name>foo</name> <predicate> <equals> <function>position</function> <constant-number>1</constant-number> </equals> </predicate> </step> </x:foo-path> ... <call-template name="eval-simple-xpath"> <xsl:with-param name="xpath" select="document('')/*/x:foo-path/> ... The above certainly needs a lot of work, it's only the product of less than thirty minutes of thinking... Regards J.Pietschmann XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] character entities, David Carlisle | Thread | [xsl] effecient inline multi-condit, Jeff Beadle |
[xsl] xsl fop - internal link, Hesselberth, Jan | Date | Re: [xsl] big recursive function, Graham Seaman |
Month |