Hi Stefan, Many thanks for your thoughts. I hadn't considered just executing an XPath query directly against the XSL as simple XML – but that works! I combined this idea with your xpath expression and now have a function that will return the correct value: def get_variable_from_xsl(variable_name, xsl): xpath_results = xsl.xpath("//xsl:variable[@name=$name]", name=variable_name, namespaces={'xsl':'http://www.w3.org/1999/XSL/Transform' }) for xpath_result in xpath_results: if xpath_result.get('name') == variable_name: for xpath_child in xpath_result.getchildren(): if 'select' in xpath_child.keys(): return xpath_child.get('select') return None destination_url = get_variable_from_xsl('destination_url', xsl) print(f"destination_url = {destination_url}") Which returns: destination_url = 'https://my.domain.example.com/' Thanks again! aid On Wed, 10 Apr 2019 at 18:25, Stefan Behnel <stefan_ml@behnel.de> wrote:
Adrian Bool schrieb am 10.04.19 um 10:49:
I'm trying to extract from data from XSL files on an IBM DataPower system. I can't change the XSLT files - and therefore need to work around their current structure to get the info I need.
Well, XSL is XML, so you can always post-process the XSL document after parsing it as XML, before you pass it into the XSLT() constructor.
I'm doing this from within Python 3.7 using etree.__version__ 4.3.3.
Here are my imports, a dummy XML object and a cutdown version of the XSL file from the IBM system:
from lxml import etree from textwrap import dedent
xml = etree.XML("""<root></root>""")
xsl = etree.XML(dedent( """<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dp="http://www.datapower.com/extensions" extension-element-prefixes="dp">
<xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy>
<xsl:variable name="destination_url"> <xsl:value-of select="'https://my.domain.example.com/'" /> </xsl:variable>
<!--Set the destination URL in the context variable--> <dp:set-variable name="'var://context/mpgw/Destination'" value="$destination_url" />
I don't think I've ever tried this myself in lxml. I guess I would have expected value="{$destination_url}" rather than the plain variable reference here. Can't say how XSLT is meant to deal with this.
</xsl:template> </xsl:stylesheet> """))
My goal is to use lxml to process this file and extract the contents of
the
DataPower variable 'var://context/mpgw/Destination' - i.e. the contents of the xsl:variable $destination_url - in the above case ' https://my.domain.example.com/'.
I've created an XSLT extension for the "dp:set-variable" element to try to capture this information:
class MyExtElement(etree.XSLTExtension): def execute(self, context, self_node, input_node, output_parent): if self_node.tag == '{ http://www.datapower.com/extensions}set-variable': print(f"Setting variable of name {self_node.get('name')} to value {self_node.get('value')}")
extensions = { ('http://www.datapower.com/extensions', 'set-variable') : MyExtElement() } result = etree.XSLT(xsl, extensions=extensions)(xml) print(f"Result: {result}")
When this is being called; instead of the value of destination_url I'm getting the static "$destination_url" string instead - with the output of the above script being:
Setting variable of name 'var://context/mpgw/Destination' to value $destination_url Result: <?xml version="1.0"?> <root/>
I am rather suprised that the $destination_url xsl:variable was not being evaluated - does anyone know why this is the case?
Given the above, I've been trying to find a way to access the $destination_url xsl:variable from within my XSLTExtension - but unfortunately with no luck.
Did you try looking it up in the XSL document via XPath? Something like
.xpath("//xsl:variable[@name=$name]", name="destination_url")
(plus namespaces)
Stefan _________________________________________________________________ Mailing list for the lxml Python XML toolkit - http://lxml.de/ lxml@lxml.de https://mailman-mail5.webfaction.com/listinfo/lxml