[email protected] schrieb am 01.04.21 um 13:11:
> Hi Adrian/Stefan,
> Apologies for dredging up a 2-year-old thread but I've hit the same issue and 
> found that although the posted solution works for variables declared with 
> simple string values, it fails when considering xsl:param values or 
> "calculated" values.  Consider:
> 
> <xsl:stylesheet version="1.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; xmlns:abc="bar" 
> extension-element-prefixes="abc">
>     <xsl:output method="xml"/>
>     <xsl:param name="param1">default param value</xsl:param>
> 
>     <xsl:template match="/">
>           <xsl:variable name="var1" select="concat( 'http://', $param1 )"/>
>           <abc:foo attr1="{$var1}"/>
>           <baz><xsl:value-of select="concat( 'XSLT ouput: ', $var1 )"/></baz>
>     </xsl:template>
> 
> </xsl:stylesheet> 
> 
> Now let's say I want to receive the value of "$var1" in my extension-element 
> foo():
> 
> #!/usr/local/bin/python3
> # -*- coding: utf-8 -*-
> 
> import sys
> 
> from lxml import etree
> from copy import deepcopy
> 
> class FooExtensionElement( etree.XSLTExtension ):
> 
>     def execute( self, context, self_node, input_node, output_parent ):
>         print( "attr1: {}".format( self_node.get( "attr1" )))
> 
> parser = etree.XMLParser( load_dtd=True )
> extensions = { 
>     ( 'bar', 'foo' ) : FooExtensionElement()
> }
> transformer = etree.XSLT( etree.parse( sys.stdin, parser ), extensions = 
> extensions )
> xml_doc = etree.XML( '<dummy/>' )
> result = transformer( xml_doc, param1=etree.XSLT.strparam( "passed param 
> value" ))
> print( result ) 
> 
> When run, the output is:
> 
> attr1: {$var1}
> <?xml version="1.0"?>
> <baz bif="http://passed param value">XSLT ouput: http://passed param 
> value</baz>
> 
> This shows that:
> * self_node.get( "attr1" ) returns the literal string "{$var1}" in execute(), 
> i.e. the transformer has not evaluated {$var1} when passing it to 
> abc:foo/@attr1
> * baz/@bif gets the evaluated value of {$var1} as expected
> 
> If I were to perform the solution suggested below and lookup //xsl:variable[ 
> @name = 'var1']/@select from within execute(), it would return the string 
> "concat( 'http://', $param1 )"
> I could attempt to evaluate this in self_node.xpath(), but I don't have 
> access to the value of $param1, right?
> So this would result in: lxml.etree.XPathEvalError: Undefined variable
> What if I first looked up the value of $param1 in the same way as suggested 
> below for xsl:variable?
> //xsl:param[ @name = 'param1']/text() would return "default param value", NOT 
> the actual value ("passed param value") which was passed in: AFAIK, I have 
> *no* way to access that value from execute().

Hmm, interesting problem. Thanks for bringing it up.


> This problem goes away if evaluation of  {$xyz} -syntax is honored for 
> extension-elements.  As demonstrated above, this is already working perfectly 
> for elements in the XSL which have no namespace (the "baz" element in my 
> example).  Is there a fundamental reason why extension-elements are excluded 
> from these evaluations?

The evaluation of the content and attributes of an extension element
(including their order and semantics) is specific to the element, and thus
needs to be done explicitly.


> If this contravenes XSLT convention, is it possible to place a map of 
> variable/param names and their values within the 'context' parameter passed 
> to the execute() function so that extension elements can perform their own 
> lookup?

I think it could be solved by providing an XPath entry point that knows
about the current XSLT context, i.e. variables and parameters. Could be a
method on the extension class.

However, I also see an advantage in providing access to the current name
mappings. That would generally be nice to have in an extension element, and
thus potentially cover a wider range of use cases.

I'd be happy to receive a PR that implements this.

Stefan
_______________________________________________
lxml - The Python XML Toolkit mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/lxml.python.org/
Member address: [email protected]

Reply via email to