5

I am developing a simple xml logfile class using lxml in Python.

My approach so far has been to use two files. A well-formed XML file which includes a second file which is a XML fragment. I am using an xi:include element. This way XML fragment can be updated efficiently by simply appending <event> elements to the end of the file.

The well formed XML file ('logfile.xml') looks like this:

 <?xml version="1.0"?>
<logfile>
<event xmlns:xi="http://www.w3.org/2001/XInclude">
    <xi:include href="events.xml"/>
</event>
</logfile>

The xml fragment ('events.xml') looks like this:

<event>
     <data></data>
</event>
<event>
     <data></data>
</event>
<event>
     <data></data>
</event>

My goal is to end up with:

<?xml version="1.0"?>
 <logfile>
    <event>
         <data></data>
    </event>
    <event>
         <data></data>
    </event>
    <event>
         <data></data>
    </event>
 </logfile>

In python I am using the xinclude method to process the xi:include element in my well formed XML file ('logfile.xml'). This works but only if there is one <event> element is the XML fragment ('events.xml')

My python code:

tree = etree.parse('logfile.xml')
tree.xinclude()
root = tree.getroot()
print etree.tostring(self.logfileNode, pretty_print=True, xml_declaration=True, encoding='UTF-8')

The error I am seeing:

lxml.etree.XIncludeError: Extra content at the end of the document

I could contain the events in another element, but this doesn't lend itself well to appending data to the end of the XML fragment document.

zetabit
  • 96
  • 1
  • 6
  • try doing this- add tag in beginning of the events.xml file, than add tag in the end of file. may be this can help – RanRag Jan 11 '12 at 22:58

1 Answers1

3

The document referenced by xi:xinclude must be a complete xml document ("complete xml infoset"). Your events.xml is not a valid xml document because you don't have a single root containing element.

You might be able to include just a subset by using the xpointer attribute to select the event elements. I'm not sure lxml supports this attribute, however.

Francis Avila
  • 31,233
  • 6
  • 58
  • 96
  • The `xpointer` attribute _is_ supported by lxml, but it won't help, because the OP wants the "events" file to be an xml fragment. But as you rightly say: it just can't be. – ekhumoro Jan 12 '12 at 00:21
  • But he *could* add an `events` root to events.xml and then include with something like ``, right? – Francis Avila Jan 12 '12 at 02:05
  • He says he wants to append `` elements _directly_ to the end of `events.xml`, so that would preclude an enclosing tag. His only purpose in trying to use `xinclude` was to insert an xml fragment into a `` root element. – ekhumoro Jan 12 '12 at 03:03
  • @ekhumoro - exactly, I want be able to append events just by writing to the end of the events.xml file. This way I don't need to parse (& load into memory) the events.xml each time I want to append an event. I could manually write a closing root tag the the events.xml (e.g. ) but I was wondering if there was a better way. – zetabit Jan 12 '12 at 14:09
  • It's not as simple as a file append, but you don't necessarily need to load the whole thing into memory. You can use streaming parsing. See [iterparse and iterwalk](http://lxml.de/parsing.html#iterparse-and-iterwalk). – Francis Avila Jan 12 '12 at 18:08