| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- ==============================
- 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 Cython_.
- .. _`etreepublic.pxd`: https://github.com/lxml/lxml/blob/master/src/lxml/includes/etreepublic.pxd
- .. _Cython: https://cython.org
- .. contents::
- ..
- 1 Passing generated trees through Python
- 2 Writing external modules in Cython
- 3 Writing external modules in C
- Passing generated trees through Python
- --------------------------------------
- This is the most simple way to integrate with lxml. It does not require
- any C-level integration but uses a Python function to wrap an externally
- generated libxml2 document in lxml.
- The external module that creates the libxml2 tree must pack the document
- pointer into a `PyCapsule <https://docs.python.org/3/c-api/capsule.html>`_
- object. This can then be passed into lxml with the function
- ``lxml.etree.adopt_external_document()``. It also takes an optional lxml
- parser instance to associate with the document, in order to configure the
- Element class lookup, relative URL lookups, etc.
- See the `API reference <api/lxml.etree-module.html#adopt_external_document>`_
- for further details.
- The same functionality is available as part of the public C-API in form
- of the C function ``adoptExternalDocument()``.
- Writing external modules in Cython
- ----------------------------------
- This is the easiest way of extending lxml at the C level. A Cython_
- module should start like this::
- # My Cython extension
- # directive pointing compiler to lxml header files;
- # use ``aliases={"LXML_PACKAGE_DIR": lxml.__path__}``
- # argument to cythonize in setup.py to dynamically
- # determine dir at compile time
- # distutils: include_dirs = LXML_PACKAGE_DIR
- # import the public functions and classes of lxml.etree
- cimport lxml.includes.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 lxml.includes.etreepublic cimport ElementBase
- cdef class NewElementClass(ElementBase):
- def set_value(self, myval):
- self.set("my_attribute", myval)
- etree.set_element_class_lookup(
- etree.ElementDefaultClassLookup(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.
|