api.txt 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. ===========================
  2. APIs specific to lxml.etree
  3. ===========================
  4. lxml.etree tries to follow established APIs wherever possible. Sometimes,
  5. however, the need to expose a feature in an easy way led to the invention of a
  6. new API. This page describes the major differences and a few additions to the
  7. main ElementTree API.
  8. For a complete reference of the API, see the `generated API
  9. documentation`_.
  10. Separate pages describe the support for `parsing XML`_, executing `XPath and
  11. XSLT`_, `validating XML`_ and interfacing with other XML tools through the
  12. `SAX-API`_.
  13. lxml is extremely extensible through `XPath functions in Python`_, custom
  14. `Python element classes`_, custom `URL resolvers`_ and even `at the C-level`_.
  15. .. _`parsing XML`: parsing.html
  16. .. _`XPath and XSLT`: xpathxslt.html
  17. .. _`validating XML`: validation.html
  18. .. _`SAX-API`: sax.html
  19. .. _`XPath functions in Python`: extensions.html
  20. .. _`Python element classes`: element_classes.html
  21. .. _`at the C-level`: capi.html
  22. .. _`URL resolvers`: resolvers.html
  23. .. _`generated API documentation`: api/index.html
  24. .. contents::
  25. ..
  26. 1 lxml.etree
  27. 2 Other Element APIs
  28. 3 Trees and Documents
  29. 4 Iteration
  30. 5 Error handling on exceptions
  31. 6 Error logging
  32. 7 Serialisation
  33. 8 Incremental XML generation
  34. 9 CDATA
  35. 10 XInclude and ElementInclude
  36. ..
  37. >>> from io import BytesIO
  38. >>> def StringIO(s=None):
  39. ... if isinstance(s, str): s = s.encode("UTF-8")
  40. ... return BytesIO(s)
  41. lxml.etree
  42. ----------
  43. lxml.etree tries to follow the `ElementTree API`_ wherever it can. There are
  44. however some incompatibilities (see `compatibility`_). The extensions are
  45. documented here.
  46. .. _`ElementTree API`: http://effbot.org/zone/element-index.htm
  47. .. _`compatibility`: compatibility.html
  48. If you need to know which version of lxml is installed, you can access the
  49. ``lxml.etree.LXML_VERSION`` attribute to retrieve a version tuple. Note,
  50. however, that it did not exist before version 1.0, so you will get an
  51. AttributeError in older versions. The versions of libxml2 and libxslt are
  52. available through the attributes ``LIBXML_VERSION`` and ``LIBXSLT_VERSION``.
  53. The following examples usually assume this to be executed first:
  54. .. sourcecode:: pycon
  55. >>> from lxml import etree
  56. ..
  57. >>> import sys
  58. >>> from lxml import etree as _etree
  59. >>> if sys.version_info[0] >= 3:
  60. ... class etree_mock(object):
  61. ... def __getattr__(self, name): return getattr(_etree, name)
  62. ... def tostring(self, *args, **kwargs):
  63. ... s = _etree.tostring(*args, **kwargs)
  64. ... if isinstance(s, bytes) and bytes([10]) in s: s = s.decode("utf-8") # CR
  65. ... if s[-1] == '\n': s = s[:-1]
  66. ... return s
  67. ... else:
  68. ... class etree_mock(object):
  69. ... def __getattr__(self, name): return getattr(_etree, name)
  70. ... def tostring(self, *args, **kwargs):
  71. ... s = _etree.tostring(*args, **kwargs)
  72. ... if s[-1] == '\n': s = s[:-1]
  73. ... return s
  74. >>> etree = etree_mock()
  75. Other Element APIs
  76. ------------------
  77. While lxml.etree itself uses the ElementTree API, it is possible to replace
  78. the Element implementation by `custom element subclasses`_. This has been
  79. used to implement well-known XML APIs on top of lxml. For example, lxml ships
  80. with a data-binding implementation called `objectify`_, which is similar to
  81. the `Amara bindery`_ tool.
  82. lxml.etree comes with a number of `different lookup schemes`_ to customize the
  83. mapping between libxml2 nodes and the Element classes used by lxml.etree.
  84. .. _`custom element subclasses`: element_classes.html
  85. .. _`objectify`: objectify.html
  86. .. _`different lookup schemes`: element_classes.html#setting-up-a-class-lookup-scheme
  87. .. _`Amara bindery`: http://uche.ogbuji.net/tech/4suite/amara/
  88. Trees and Documents
  89. -------------------
  90. Compared to the original ElementTree API, lxml.etree has an extended tree
  91. model. It knows about parents and siblings of elements:
  92. .. sourcecode:: pycon
  93. >>> root = etree.Element("root")
  94. >>> a = etree.SubElement(root, "a")
  95. >>> b = etree.SubElement(root, "b")
  96. >>> c = etree.SubElement(root, "c")
  97. >>> d = etree.SubElement(root, "d")
  98. >>> e = etree.SubElement(d, "e")
  99. >>> b.getparent() == root
  100. True
  101. >>> print(b.getnext().tag)
  102. c
  103. >>> print(c.getprevious().tag)
  104. b
  105. Elements always live within a document context in lxml. This implies that
  106. there is also a notion of an absolute document root. You can retrieve an
  107. ElementTree for the root node of a document from any of its elements.
  108. .. sourcecode:: pycon
  109. >>> tree = d.getroottree()
  110. >>> print(tree.getroot().tag)
  111. root
  112. Note that this is different from wrapping an Element in an ElementTree. You
  113. can use ElementTrees to create XML trees with an explicit root node:
  114. .. sourcecode:: pycon
  115. >>> tree = etree.ElementTree(d)
  116. >>> print(tree.getroot().tag)
  117. d
  118. >>> etree.tostring(tree)
  119. b'<d><e/></d>'
  120. ElementTree objects are serialised as complete documents, including
  121. preceding or trailing processing instructions and comments.
  122. All operations that you run on such an ElementTree (like XPath, XSLT, etc.)
  123. will understand the explicitly chosen root as root node of a document. They
  124. will not see any elements outside the ElementTree. However, ElementTrees do
  125. not modify their Elements:
  126. .. sourcecode:: pycon
  127. >>> element = tree.getroot()
  128. >>> print(element.tag)
  129. d
  130. >>> print(element.getparent().tag)
  131. root
  132. >>> print(element.getroottree().getroot().tag)
  133. root
  134. The rule is that all operations that are applied to Elements use either the
  135. Element itself as reference point, or the absolute root of the document that
  136. contains this Element (e.g. for absolute XPath expressions). All operations
  137. on an ElementTree use its explicit root node as reference.
  138. Iteration
  139. ---------
  140. The ElementTree API makes Elements iterable to supports iteration over their
  141. children. Using the tree defined above, we get:
  142. .. sourcecode:: pycon
  143. >>> [ child.tag for child in root ]
  144. ['a', 'b', 'c', 'd']
  145. To iterate in the opposite direction, use the builtin ``reversed()`` function.
  146. Tree traversal should use the ``element.iter()`` method:
  147. .. sourcecode:: pycon
  148. >>> [ el.tag for el in root.iter() ]
  149. ['root', 'a', 'b', 'c', 'd', 'e']
  150. lxml.etree also supports this, but additionally features an extended API for
  151. iteration over the children, following/preceding siblings, ancestors and
  152. descendants of an element, as defined by the respective XPath axis:
  153. .. sourcecode:: pycon
  154. >>> [ child.tag for child in root.iterchildren() ]
  155. ['a', 'b', 'c', 'd']
  156. >>> [ child.tag for child in root.iterchildren(reversed=True) ]
  157. ['d', 'c', 'b', 'a']
  158. >>> [ sibling.tag for sibling in b.itersiblings() ]
  159. ['c', 'd']
  160. >>> [ sibling.tag for sibling in c.itersiblings(preceding=True) ]
  161. ['b', 'a']
  162. >>> [ ancestor.tag for ancestor in e.iterancestors() ]
  163. ['d', 'root']
  164. >>> [ el.tag for el in root.iterdescendants() ]
  165. ['a', 'b', 'c', 'd', 'e']
  166. Note how ``element.iterdescendants()`` does not include the element
  167. itself, as opposed to ``element.iter()``. The latter effectively
  168. implements the 'descendant-or-self' axis in XPath.
  169. All of these iterators support one (or more, since lxml 3.0) additional
  170. arguments that filter the generated elements by tag name:
  171. .. sourcecode:: pycon
  172. >>> [ child.tag for child in root.iterchildren('a') ]
  173. ['a']
  174. >>> [ child.tag for child in d.iterchildren('a') ]
  175. []
  176. >>> [ el.tag for el in root.iterdescendants('d') ]
  177. ['d']
  178. >>> [ el.tag for el in root.iter('d') ]
  179. ['d']
  180. >>> [ el.tag for el in root.iter('d', 'a') ]
  181. ['a', 'd']
  182. Note that the order of the elements is determined by the iteration order,
  183. which is the document order in most cases (except for preceding siblings
  184. and ancestors, where it is the reversed document order). The order of
  185. the tag selection arguments is irrelevant, as you can see in the last
  186. example.
  187. The most common way to traverse an XML tree is depth-first, which
  188. traverses the tree in document order. This is implemented by the
  189. ``.iter()`` method. While there is no dedicated method for
  190. breadth-first traversal, it is almost as simple if you use the
  191. ``collections.deque`` type.
  192. .. sourcecode:: pycon
  193. >>> root = etree.XML('<root><a><b/><c/></a><d><e/></d></root>')
  194. >>> print(etree.tostring(root, pretty_print=True, encoding='unicode'))
  195. <root>
  196. <a>
  197. <b/>
  198. <c/>
  199. </a>
  200. <d>
  201. <e/>
  202. </d>
  203. </root>
  204. >>> from collections import deque
  205. >>> queue = deque([root])
  206. >>> while queue:
  207. ... el = queue.popleft() # pop next element
  208. ... queue.extend(el) # append its children
  209. ... print(el.tag)
  210. root
  211. a
  212. d
  213. b
  214. c
  215. e
  216. See also the section on the utility functions ``iterparse()`` and
  217. ``iterwalk()`` in the `parser documentation`_.
  218. .. _`parser documentation`: parsing.html#iterparse-and-iterwalk
  219. Error handling on exceptions
  220. ----------------------------
  221. Libxml2 provides error messages for failures, be it during parsing, XPath
  222. evaluation or schema validation. The preferred way of accessing them is
  223. through the local ``error_log`` property of the respective evaluator or
  224. transformer object. See their documentation for details.
  225. However, lxml also keeps a global error log of all errors that occurred at the
  226. application level. Whenever an exception is raised, you can retrieve the
  227. errors that occurred and "might have" lead to the problem from the error log
  228. copy attached to the exception:
  229. .. sourcecode:: pycon
  230. >>> etree.clear_error_log()
  231. >>> broken_xml = '''
  232. ... <root>
  233. ... <a>
  234. ... </root>
  235. ... '''
  236. >>> try:
  237. ... etree.parse(StringIO(broken_xml))
  238. ... except etree.XMLSyntaxError, e:
  239. ... pass # just put the exception into e
  240. ..
  241. >>> etree.clear_error_log()
  242. >>> try:
  243. ... etree.parse(StringIO(broken_xml))
  244. ... except etree.XMLSyntaxError:
  245. ... import sys; e = sys.exc_info()[1]
  246. Once you have caught this exception, you can access its ``error_log`` property
  247. to retrieve the log entries or filter them by a specific type, error domain or
  248. error level:
  249. .. sourcecode:: pycon
  250. >>> log = e.error_log.filter_from_level(etree.ErrorLevels.FATAL)
  251. >>> print(log[0])
  252. <string>:4:8:FATAL:PARSER:ERR_TAG_NAME_MISMATCH: Opening and ending tag mismatch: a line 3 and root
  253. This might look a little cryptic at first, but it is the information that
  254. libxml2 gives you. At least the message at the end should give you a hint
  255. what went wrong and you can see that the fatal errors (FATAL) happened during
  256. parsing (PARSER) lines 4, column 8 and line 5, column 1 of a string (<string>,
  257. or the filename if available). Here, PARSER is the so-called error domain,
  258. see ``lxml.etree.ErrorDomains`` for that. You can get it from a log entry
  259. like this:
  260. .. sourcecode:: pycon
  261. >>> entry = log[0]
  262. >>> print(entry.domain_name)
  263. PARSER
  264. >>> print(entry.type_name)
  265. ERR_TAG_NAME_MISMATCH
  266. >>> print(entry.filename)
  267. <string>
  268. There is also a convenience attribute ``error_log.last_error`` that returns the
  269. last error or fatal error that occurred, so that it's easy to test if there was
  270. an error at all. Note, however, that there might have been more than one error,
  271. and the first error that occurred might be more relevant in some cases.
  272. Error logging
  273. -------------
  274. lxml.etree supports logging libxml2 messages to the Python stdlib logging
  275. module. This is done through the ``etree.PyErrorLog`` class. It disables the
  276. error reporting from exceptions and forwards log messages to a Python logger.
  277. To use it, see the descriptions of the function ``etree.useGlobalPythonLog``
  278. and the class ``etree.PyErrorLog`` for help. Note that this does not affect
  279. the local error logs of XSLT, XMLSchema, etc.
  280. Serialisation
  281. -------------
  282. C14N
  283. ....
  284. lxml.etree has support for `C14N 1.0 <https://www.w3.org/TR/xml-exc-c14n/>`_
  285. and `C14N 2.0 <https://www.w3.org/TR/xml-c14n2/>`_. When serialising an XML
  286. tree using ``ElementTree.write()`` or ``tostring()``, you can pass the option
  287. ``method="c14n"`` for 1.0 or ``method="c14n2"`` for 2.0.
  288. Additionally, there is a function ``etree.canonicalize()`` which can be used
  289. to convert serialised XML to its canonical form directly, without creating
  290. a tree in memory. By default, it returns the canonical output, but can be
  291. directed to write it to a file instead.
  292. .. sourcecode:: pycon
  293. >>> c14n_xml = etree.canonicalize("<root><test z='1' y='2'/></root>")
  294. >>> print(c14n_xml)
  295. <root><test y="2" z="1"></test></root>
  296. Pretty printing
  297. ...............
  298. Functions like ``ElementTree.write()`` and ``tostring()`` also support pretty
  299. printing XML through a keyword argument:
  300. .. sourcecode:: pycon
  301. >>> root = etree.XML("<root><test/></root>")
  302. >>> etree.tostring(root)
  303. b'<root><test/></root>'
  304. >>> print(etree.tostring(root, pretty_print=True))
  305. <root>
  306. <test/>
  307. </root>
  308. Note the newline that is appended at the end when pretty printing the
  309. output. It was added in lxml 2.0.
  310. XML declaration
  311. ...............
  312. By default, lxml (just as ElementTree) outputs the XML declaration only if it
  313. is required by the standard:
  314. .. sourcecode:: pycon
  315. >>> unicode_root = etree.Element( u"t\u3120st" )
  316. >>> unicode_root.text = u"t\u0A0Ast"
  317. >>> etree.tostring(unicode_root, encoding="utf-8")
  318. b'<t\xe3\x84\xa0st>t\xe0\xa8\x8ast</t\xe3\x84\xa0st>'
  319. >>> print(etree.tostring(unicode_root, encoding="iso-8859-1"))
  320. <?xml version='1.0' encoding='iso-8859-1'?>
  321. <t&#12576;st>t&#2570;st</t&#12576;st>
  322. Also see the general remarks on `Unicode support`_.
  323. .. _`Unicode support`: parsing.html#python-unicode-strings
  324. You can enable or disable the declaration explicitly by passing another
  325. keyword argument for the serialisation:
  326. .. sourcecode:: pycon
  327. >>> print(etree.tostring(root, xml_declaration=True))
  328. <?xml version='1.0' encoding='ASCII'?>
  329. <root><test/></root>
  330. >>> unicode_root.clear()
  331. >>> etree.tostring(unicode_root, encoding="UTF-16LE",
  332. ... xml_declaration=False)
  333. b'<\x00t\x00 1s\x00t\x00/\x00>\x00'
  334. Note that a standard compliant XML parser will not consider the last line
  335. well-formed XML if the encoding is not explicitly provided somehow, e.g. in an
  336. underlying transport protocol:
  337. .. sourcecode:: pycon
  338. >>> notxml = etree.tostring(unicode_root, encoding="UTF-16LE",
  339. ... xml_declaration=False)
  340. >>> root = etree.XML(notxml) #doctest: +ELLIPSIS
  341. Traceback (most recent call last):
  342. ...
  343. lxml.etree.XMLSyntaxError: ...
  344. Since version 2.3, the serialisation can override the internal subset
  345. of the document with a user provided DOCTYPE:
  346. .. sourcecode:: pycon
  347. >>> xml = '<!DOCTYPE root>\n<root/>'
  348. >>> tree = etree.parse(StringIO(xml))
  349. >>> print(etree.tostring(tree))
  350. <!DOCTYPE root>
  351. <root/>
  352. >>> print(etree.tostring(tree,
  353. ... doctype='<!DOCTYPE root SYSTEM "/tmp/test.dtd">'))
  354. <!DOCTYPE root SYSTEM "/tmp/test.dtd">
  355. <root/>
  356. The content will be encoded, but otherwise copied verbatim into the
  357. output stream. It is therefore left to the user to take care for a
  358. correct doctype format, including the name of the root node.
  359. Incremental XML generation
  360. --------------------------
  361. Since version 3.1, lxml provides an ``xmlfile`` API for incrementally
  362. generating XML using the ``with`` statement. It's main purpose is to
  363. freely and safely mix surrounding elements with pre-built in-memory
  364. trees, e.g. to write out large documents that consist mostly of
  365. repetitive subtrees (like database dumps). But it can be useful in
  366. many cases where memory consumption matters or where XML is naturally
  367. generated in sequential steps. Since lxml 3.4.1, there is an equivalent
  368. context manager for HTML serialisation called ``htmlfile``.
  369. The API can serialise to real files (given as file path or file
  370. object), as well as file-like objects, e.g. ``io.BytesIO()``.
  371. Here is a simple example::
  372. >>> f = BytesIO()
  373. >>> with etree.xmlfile(f) as xf:
  374. ... with xf.element('abc'):
  375. ... xf.write('text')
  376. >>> print(f.getvalue().decode('utf-8'))
  377. <abc>text</abc>
  378. ``xmlfile()`` accepts a file path as first argument, or a file(-like)
  379. object, as in the example above. In the first case, it takes care to
  380. open and close the file itself, whereas file(-like) objects are not
  381. closed by default. This is left to the code that opened them. Since
  382. lxml 3.4, however, you can pass the argument ``close=True`` to make
  383. lxml call the object's ``.close()`` method when exiting the xmlfile
  384. context manager.
  385. To insert pre-constructed Elements and subtrees, just pass them
  386. into ``write()``::
  387. >>> f = BytesIO()
  388. >>> with etree.xmlfile(f) as xf:
  389. ... with xf.element('abc'):
  390. ... with xf.element('in'):
  391. ...
  392. ... for value in '123':
  393. ... # construct a really complex XML tree
  394. ... el = etree.Element('xyz', attr=value)
  395. ...
  396. ... xf.write(el)
  397. ...
  398. ... # no longer needed, discard it right away!
  399. ... el = None
  400. >>> print(f.getvalue().decode('utf-8'))
  401. <abc><in><xyz attr="1"/><xyz attr="2"/><xyz attr="3"/></in></abc>
  402. It is a common pattern to have one or more nested ``element()``
  403. blocks, and then build in-memory XML subtrees in a loop (using the
  404. ElementTree API, the builder API, XSLT, or whatever) and write them
  405. out into the XML file one after the other. That way, they can be
  406. removed from memory right after their construction, which can largely
  407. reduce the memory footprint of an application, while keeping the
  408. overall XML generation easy, safe and correct.
  409. Together with Python coroutines, this can be used to generate XML
  410. in an asynchronous, non-blocking fashion, e.g. for a stream protocol
  411. like the instant messaging protocol
  412. `XMPP <https://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol>`_::
  413. def writer(out_stream):
  414. with xmlfile(out_stream) as xf:
  415. with xf.element('{http://etherx.jabber.org/streams}stream'):
  416. while True:
  417. el = (yield)
  418. xf.write(el)
  419. xf.flush()
  420. w = writer(stream)
  421. next(w) # start writing (run up to 'yield')
  422. Then, whenever XML elements are available for writing, call
  423. ::
  424. w.send(element)
  425. And when done::
  426. w.close()
  427. Note the additional ``xf.flush()`` call in the example above, which is
  428. available since lxml 3.4. Normally, the output stream is buffered to
  429. avoid excessive I/O calls. Whenever the internal buffer fills up, its
  430. content is written out. In the case above, however, we want to make
  431. sure that each message that we write (i.e. each element subtree) is
  432. written out immediately, so we flush the content explicitly at the
  433. right point.
  434. Alternatively, if buffering is not desired at all, it can be disabled
  435. by passing the flag ``buffered=False`` into ``xmlfile()`` (also since
  436. lxml 3.4).
  437. Here is a similar example using an async coroutine in Py3.5 or later, which is
  438. supported since lxml 4.0. The output stream is expected to have methods
  439. ``async def write(self, data)`` and ``async def close(self)`` in this case.
  440. ::
  441. async def writer(out_stream, xml_messages):
  442. async with xmlfile(out_stream) as xf:
  443. async with xf.element('{http://etherx.jabber.org/streams}stream'):
  444. async for el in xml_messages:
  445. await xf.write(el)
  446. await xf.flush()
  447. class DummyAsyncOut(object):
  448. async def write(self, data):
  449. print(data.decode('utf8'))
  450. async def close(self):
  451. pass
  452. stream = DummyAsyncOut()
  453. async_writer = writer(stream, async_message_stream)
  454. CDATA
  455. -----
  456. By default, lxml's parser will strip CDATA sections from the tree and
  457. replace them by their plain text content. As real applications for
  458. CDATA are rare, this is the best way to deal with this issue.
  459. However, in some cases, keeping CDATA sections or creating them in a
  460. document is required to adhere to existing XML language definitions.
  461. For these special cases, you can instruct the parser to leave CDATA
  462. sections in the document:
  463. .. sourcecode:: pycon
  464. >>> parser = etree.XMLParser(strip_cdata=False)
  465. >>> root = etree.XML('<root><![CDATA[test]]></root>', parser)
  466. >>> root.text
  467. 'test'
  468. >>> etree.tostring(root)
  469. b'<root><![CDATA[test]]></root>'
  470. Note how the ``.text`` property does not give any indication that the
  471. text content is wrapped by a CDATA section. If you want to make sure
  472. your data is wrapped by a CDATA block, you can use the ``CDATA()``
  473. text wrapper:
  474. .. sourcecode:: pycon
  475. >>> root.text = 'test'
  476. >>> root.text
  477. 'test'
  478. >>> etree.tostring(root)
  479. b'<root>test</root>'
  480. >>> root.text = etree.CDATA(root.text)
  481. >>> root.text
  482. 'test'
  483. >>> etree.tostring(root)
  484. b'<root><![CDATA[test]]></root>'
  485. XInclude and ElementInclude
  486. ---------------------------
  487. You can let lxml process xinclude statements in a document by calling the
  488. xinclude() method on a tree:
  489. .. sourcecode:: pycon
  490. >>> data = StringIO('''\
  491. ... <doc xmlns:xi="http://www.w3.org/2001/XInclude">
  492. ... <foo/>
  493. ... <xi:include href="doc/test.xml" />
  494. ... </doc>''')
  495. >>> tree = etree.parse(data)
  496. >>> tree.xinclude()
  497. >>> print(etree.tostring(tree.getroot()))
  498. <doc xmlns:xi="http://www.w3.org/2001/XInclude">
  499. <foo/>
  500. <a xml:base="doc/test.xml"/>
  501. </doc>
  502. Note that the ElementTree compatible ElementInclude_ module is also supported
  503. as ``lxml.ElementInclude``. It has the additional advantage of supporting
  504. custom `URL resolvers`_ at the Python level. The normal XInclude mechanism
  505. cannot deploy these. If you need ElementTree compatibility or custom
  506. resolvers, you have to stick to the external Python module.
  507. .. _ElementInclude: http://effbot.org/zone/element-xinclude.htm