# The XSLT C library for Gnome

## Python and bindings

Main Menu

- Home
- Wiki
- Introduction
- Documentation
- Reporting bugs and getting help
- How to help
- Downloads
- FAQ
- News
- The xsltproc tool
- DocBook
- The programming API
- Python and bindings
- Library internals
- Writing extensions
- Contributions
- libexslt
- flat page, stylesheet
- API Menu
- ChangeLog

Related links

- Tutorial, Tutorial2
- Man page for xsltproc
- Mail archive
- XML libxml2
- FTP
- Windows binaries
- Solaris binaries
- MacOsX binaries
- Bug Tracker
- XSLT with PHP
- Apache module
- Pascal bindings
- Xsldbg Debugger

API Indexes

- Alphabetic
- Constructors
- Functions/Types
- Modules
- Symbols

There is a number of language bindings and wrappers available for libxml2,the list below is not exhaustive. Please contact the xml-bindings@gnome.org(archives) inorder to get updates to this list or to discuss the specific topic of libxml2or libxslt wrappers or bindings:

- MattSergeantdevelopped XML::LibXMLand XML::LibXSLT, Perl wrappers for libxml2/libxslt as part of the AxKit XML application server
- Dave Kuhlmanprovides andearlier version of the libxml/libxslt wrappers for Python
- Petr Kozelka provides Pascal units to gluelibxml2with Kylix, Delphi and other Pascal compilers
- Wai-Sun "Squidster" Chia provides bindings for Rubyandlibxml2 bindings are also available in Ruby through the libgdome-rubymodulemaintained by Tobias Peters.
- Steve Ball and contributors maintains libxml2 and libxslt bindings forTcl
- Peter Jonesmaintains C++bindings for libxslt within xmlwrapp
- Mike Phillipsprovides a moduleusing libxsltfor PHP.
- LibxmlJisan effort to create a 100% JAXP-compatible Java wrapper for libxml2 andlibxslt as part of GNU ClasspathX project.
- Patrick McPhee provides Rexx bindings fof libxml2 and libxslt, look forRexxXML.
- Satimageprovides XMLLibosax. This is an osax for Mac OS X with a set of commands toimplement in AppleScript the XML DOM, XPATH and XSLT.

The libxslt Python module depends on the libxml2 Pythonmodule.

The distribution includes a set of Python bindings, which are garanteed tobe maintained as part of the library in the future, though the Pythoninterface have not yet reached the completeness of the C API.

Stéphane Bidoulmaintains a Windows portof the Python bindings.

Note to people interested in building bindings, the API is formalized asan XML API description filewhich allows toautomate a large part of the Python bindings, this includes functiondescriptions, enums, structures, typedefs, etc... The Python script used tobuild the bindings is python/generator.py in the source distribution.

To install the Python bindings there are 2 options:

- If you use an RPM based distribution, simply install the libxml2-pythonRPMand the libxslt-pythonRPM.
- Otherwise use the libxml2-pythonmodule distributioncorresponding to your installed version oflibxml2 and libxslt. Note that to install it you will need both libxml2and libxslt installed and run "python setup.py build install" in themodule tree.

The distribution includes a set of examples and regression tests for thepython bindings in the `python/tests`directory. Here are someexcepts from those tests:

### basic.py:

This is a basic test of XSLT interfaces: loading a stylesheet and adocument, transforming the document and saving the result.

    import libxml2
    import libxslt

    styledoc = libxml2.parseFile("test.xsl")
    style = libxslt.parseStylesheetDoc(styledoc)
    doc = libxml2.parseFile("test.xml")
    result = style.applyStylesheet(doc, None)
    style.saveResultToFilename("foo", result, 0)
    style.freeStylesheet()
    doc.freeDoc()
    result.freeDoc()

The Python module is called libxslt, you will also need the libxml2 modulefor the operations on XML trees. Let's have a look at the objects manipulatedin that example and how is the processing done:

- `styledoc`: is a libxml2 document tree. It is obtained byparsing the XML file "test.xsl" containing the stylesheet.
- `style`: this is a precompiled stylesheet ready to be usedby the following transformations (note the plural form, multipletransformations can resuse the same stylesheet).
- `doc`: this is the document to apply the transformation to.In this case it is simply generated by parsing it from a file but anyother processing is possible as long as one get a libxml2 Doc. Note thatHTML tree are suitable for XSLT processing in libxslt. This is actuallyhow this page is generated !
- `result`: this is a document generated by applying thestylesheet to the document. Note that some of the stylesheet informationsmay be related to the serialization of that document and as in thisexample a specific saveResultToFilename() method of the stylesheet shouldbe used to save it to a file (in that case to "foo").

Also note the need to explicitely deallocate documents with freeDoc()except for the stylesheet document which is freed when its compiled form isgarbage collected.

### extfunc.py:

This one is a far more complex test. It shows how to modify the behaviourof an XSLT transformation by passing parameters and how to extend the XSLTengine with functions defined in python:

    import libxml2
    import libxslt
    import string

    nodeName = None
    def f(ctx, str):
        global nodeName

        #
        # Small check to verify the context is correcly accessed
        #
        try:
            pctxt = libxslt.xpathParserContext(_obj=ctx)
            ctxt = pctxt.context()
            tctxt = ctxt.transformContext()
            nodeName = tctxt.insertNode().name
        except:
            pass

        return string.upper(str)

    libxslt.registerExtModuleFunction("foo", "http://example.com/foo", f)

This code defines and register an extension function. Note that thefunction can be bound to any name (foo) and how the binding is alsoassociated to a namespace name "http://example.com/foo". From an XSLT pointof view the function just returns an upper case version of the string passedas a parameter. But the first part of the function also read some contextualinformation from the current XSLT processing environement, in that case itlooks for the current insertion node in the resulting output (either theresulting document or the Result Value Tree being generated), and saves it toa global variable for checking that the access actually worked.

For more informations on the xpathParserContext and transformContextobjects check the libray internals description.The pctxt is actually an object from a class derived from thelibxml2.xpathParserContext() with just a couple more properties including thepossibility to look up the XSLT transformation context from the XPathcontext.

    styledoc = libxml2.parseDoc("""
    <xsl:stylesheet version='1.0'
      xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
      xmlns:foo='http://example.com/foo'
      xsl:exclude-result-prefixes='foo'>

      <xsl:param name='bar'>failure</xsl:param>
      <xsl:template match='/'>
        <article><xsl:value-of select='foo:foo($bar)'/></article>
      </xsl:template>
    </xsl:stylesheet>
    """)

Here is a simple example of how to read an XML document from a pythonstring with libxml2. Note how this stylesheet:

- Uses a global parameter `bar`
- Reference the extension function f
- how the Namespace name "http://example.com/foo" has to be bound to aprefix
- how that prefix is excluded from the output
- how the function is called from the select

    style = libxslt.parseStylesheetDoc(styledoc)
    doc = libxml2.parseDoc("<doc/>")
    result = style.applyStylesheet(doc, { "bar": "'success'" })
    style.freeStylesheet()
    doc.freeDoc()

that part is identical, to the basic example except that thetransformation is passed a dictionnary of parameters. Note that the stringpassed "success" had to be quoted, otherwise it is interpreted as an XPathquery for the childs of root named "success".

    root = result.children
    if root.name != "article":
        print "Unexpected root node name"
        sys.exit(1)
    if root.content != "SUCCESS":
        print "Unexpected root node content, extension function failed"
        sys.exit(1)
    if nodeName != 'article':
        print "The function callback failed to access its context"
        sys.exit(1)

    result.freeDoc()

That part just verifies that the transformation worked, that the parametergot properly passed to the engine, that the function f() got called and thatit properly accessed the context to find the name of the insertion node.

### pyxsltproc.py:

this module is a bit too long to be described there but it is basically arewrite of the xsltproc command line interface of libxslt in Python. Itprovides nearly all the functionalities of xsltproc and can be used as a basemodule to write Python customized XSLT processors. One of the thing to noticeare:

    libxml2.lineNumbersDefault(1)
    libxml2.substituteEntitiesDefault(1)

those two calls in the main() function are needed to force the libxml2processor to generate DOM trees compliant with the XPath data model.

Daniel Veillard