views:

53

answers:

2

I'd like to do an XSL transform on a DocBook document using lxml.etree.XSLT.

Although the documentation mentions that etree.XSLT() takes a first parameter of xslt_input, I can't seem to find any docs on what this parameter is meant to be. Passing it a file that is open for reading seems to work; passing it a filename in a string does not.

edit After a sanity check, I realized that etree.XSLT takes an parsed etree._ElementTree. So . . . maybe there's a way to parse an element tree in a way that gives it a path to use for mapping relative paths? . . . investigating.

If the XML file that it is passed includes others, relative paths in those include statements are taken from the current working directory.

I'd like to use this class to transform a DocBook document, and would prefer to be able to access the DocBook XSL remotely. The Docbook XSL is pretty complex, and includes numerous other files. Is there a way that I can cause etree.XSLT to pull these files from a remote location?

A: 

The xslt_input argument requires an XSL document.

Here's a snippet of usage from http://snipplr.com/view/19433/lxml-xslt/:

from lxml.etree import XSLT,fromstring

xml = fromstring("<a key='value'>ez</a>")
xsl= fromstring("""<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output method = "html"  version="1.0" encoding="UTF-8" omit-xml-declaration="yes" standalone="yes" indent="no"  />

    <xsl:template match="a">
        <xsl:value-of select="@key"/>
    </xsl:template>

</xsl:stylesheet>""")

style = XSLT(xsl)
result = style.apply( xml)
print style.tostring(result)
Tim McNamara
I don't think you understood the question. I need to tell the XSLT object how to expand the relative paths used by include/import statements in the top-level XSL file.
intuited
You're possibly right there. I thought the question was mainly about what needed to be passed to the `__init__` method.
Tim McNamara
A: 

This is actually dead easy, I just had mental indigestion, and forgot that there was that all-important intermediate step of parsing the XSL stylesheet. It's at that point that you let it know the base URL for the stylesheet.

If you grab the stylesheet from an URL, it just deducts it from the URL. I didn't realize this was an option at first, which may have been the start of my confusion.

Otherwise you can pass the location in via the base_url parameter.

In three easy steps:

>>> xsl_url = 'http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl'
>>> document = 'path/to/document.xml'
>>> output_filename = 'path/to/transformed-document.xhtml'
>>> from lxml import etree
>>> transform = etree.XSLT(etree.parse(xsl_url))
>>> with open(document) as f:
>>>     transformed_document = transform(etree.parse(f))
>>> transformed_document.write(output_filename)

Voilà!

What I had been doing was initializing the stylesheet etree from a local file, mostly because I didn't realize that I could just pass in a URL.

intuited
Full documentation for `etree.parse` seems to be [here](http://codespeak.net/lxml/api/lxml.etree-module.html#parse).
intuited