Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Simon Sapin SimonSapin
file 94 lines (69 sloc) 2.916 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
==============================
The public C-API of lxml.etree
==============================

As of version 1.1, lxml.etree provides a public C-API. This allows external
C extensions to efficiently access public functions and classes of lxml,
without going through the Python API.

The API is described in the file `etreepublic.pxd`_, which is directly
c-importable by extension modules implemented in Pyrex_ or Cython_.

.. _`etreepublic.pxd`: https://github.com/lxml/lxml/blob/master/src/lxml/include/etreepublic.pxd
.. _Cython: http://cython.org
.. _Pyrex: http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/

.. contents::
..
   1 Writing external modules in Cython
   2 Writing external modules in C


Writing external modules in Cython
----------------------------------

This is the easiest way of extending lxml at the C level. A Cython_
(or Pyrex_) module should start like this::

    # My Cython extension

    # import the public functions and classes of lxml.etree
    cimport etreepublic as cetree

    # import the lxml.etree module in Python
    cdef object etree
    from lxml import etree

    # initialize the access to the C-API of lxml.etree
    cetree.import_lxml__etree()

From this line on, you can access all public functions of lxml.etree
from the ``cetree`` namespace like this::

    # build a tag name from namespace and element name
    py_tag = cetree.namespacedNameFromNsName("http://some/url", "myelement")

Public lxml classes are easily subclassed. For example, to implement
and set a new default element class, you can write Cython code like
the following::

    from etreepublic cimport ElementBase
    cdef class NewElementClass(ElementBase):
         def set_value(self, myval):
             self.set("my_attribute", myval)

    etree.set_element_class_lookup(
         etree.DefaultElementClassLookup(element=NewElementClass))


Writing external modules in C
-----------------------------

If you really feel like it, you can also interface with lxml.etree straight
from C code. All you have to do is include the header file for the public
API, import the ``lxml.etree`` module and then call the import function:

.. sourcecode:: c

    /* My C extension */

    /* common includes */
    #include "Python.h"
    #include "stdio.h"
    #include "string.h"
    #include "stdarg.h"
    #include "libxml/xmlversion.h"
    #include "libxml/encoding.h"
    #include "libxml/hash.h"
    #include "libxml/tree.h"
    #include "libxml/xmlIO.h"
    #include "libxml/xmlsave.h"
    #include "libxml/globals.h"
    #include "libxml/xmlstring.h"

    /* lxml.etree specific includes */
    #include "lxml-version.h"
    #include "etree_defs.h"
    #include "etree.h"

    /* setup code */
    import_lxml__etree()

Note that including ``etree.h`` does not automatically include the
header files it requires. Note also that the above list of common
includes may not be sufficient.
Something went wrong with that request. Please try again.