What is voevent-parse?¶
A lightweight library for parsing, manipulating, and generating VOEvent XML packets, built atop lxml.objectify.
voevent-parse provides convenience routines to take care of many common tasks, so that accessing those vital data elements is as simple as:
import voeventparse with open(xml_filename) as f: v = voeventparse.load(f) print "AuthorIVORN:", v.Who.AuthorIVORN #Prints e.g. ivo://nasa.gsfc.tan/gcn v.Who.AuthorIVORN = 'ivo://i.heart.python/lxml' #Alters the XML value.
As of version 0.8, voevent-parse is Python 3 compatible (tested with Python versions 2.7 & 3.4).
voevent-parse aims to make dealing with VOEvent packets easy, while remaining small, flexible, and stable enough to be suitable for use as a dependency in a range of larger projects. To achieve this, we add a user-friendly layer on top of lxml.objectify which attempts to hide the messy details of working with the sometimes lengthy VOEvent schema, and also take care of some rather obscure lxml namespace handling. However, since the objects created are just regular lxml classes, the user is free to utilise the full power of the lxml library when required.
voevent-parse is pip installable, try running:
pip install voevent-parse
Note that voevent-parse depends upon lxml, and pip will attempt to install lxml first if not already present. lxml may be installed as a system package if the version distributed with your package manager is sufficiently up-to-date (version >= 2.3). If you’re working with pip / virtualenv and not making use of system packages, then note that lxml has some prerequisites for compilation that can cause a standard pip install to fail with somewhat cryptic errors. On Ubuntu you can satisfy those requirements using:
sudo apt-get install libxml2-dev libxslt-dev
Reference documentation can be found at http://voevent-parse.readthedocs.org, or generated directly from the repository using Sphinx.
Source, Issues, Development etc.¶
I intend to mark any updates by bumping the version number accordingly. That said, if you find yourself using voevent-parse in any serious context, do drop me an email so I can keep you informed of any updates or critical bugs.
Bug reports (or even better, pull requests) are welcomed. The source code and issue tracker may be found at https://github.com/timstaley/voevent-parse.
voevent-parse also has a suite of unit-tests which may be run in the usual manner, typically using nose from the repository root directory.
The objectify library has a few syntactic quirks which can trip up new users. Firstly, you should be aware that the line root.foo actually returns an object that acts like a list of all the children of the root element with the name foo. What’s confusing is that objectify has syntactic sugar applied so that root.foo is a shortcut alias for the more explicit root.foo. This can be very confusing to the uninitiated, since it overrides some attributes of the the actual element values. To get around this, you should be aware of the accessor to the text representation of the value; .text, e.g.:
import lxml.objectify root = lxml.objectify.Element('root') root.foo = 'sometext' # Adds a child called 'foo' with value 'sometext' print root.foo # 'sometext' print len(root.foo) # 1. Wait, what? # The string value clearly does not have length==1, # the list of children called 'foo' does. print root.foo.text # 'sometext' print len(root.foo.text) # 8. Sanity prevails!
Another ‘gotcha’ is that creating multiple child elements of the same name is a bit unintuitive. Essentially, objectify works implicitly if each element has only one child:
from lxml import objectify, etree simple_root = objectify.Element('simple_root') simple_root.layer1 = None simple_root.layer1.layer2 = 5 print etree.tostring(simple_root, pretty_print=True)
But if there are multiple children then each child must be explicitly declared as an lxml Element in order to co-exist with its siblings:
from lxml import objectify, etree import math siblings_root = objectify.Element('siblings') siblings_root.bars = None siblings_root.bars.append(objectify.Element('bar')) siblings_root.bars.append(objectify.Element('bar')) siblings_root.bars.bar = math.pi siblings_root.bars.bar = 42 print etree.tostring(siblings_root, pretty_print=True)
... which is another reason to use voevent-parse as a user-friendly interface for common operations.
For some more examples, you might also try: http://www.saltycrane.com/blog/2011/07/example-parsing-xml-lxml-objectify/.
Alternative parsing libraries¶
voevent-parse was preceded by VOEventLib, which has similar aims but a different stylistic approach (see http://lib.skyalert.org/VOEventLib/VOEventLib/doc/index.html ).
In order to receive VOEvent packets, you will require a utility capable of connecting to the VOEvent backbone. Two such tools are Comet and Dakota.
Associated utility routines¶
Depending on what you want to use your VOEvents for, you may be interested in pysovo, a collection of routines for responding to VOEvents, and/or fourpiskytools, which provides basic routines for submitting VOEvents to a broker for publication.
If you make use of voevent-parse in work leading to a publication, we ask that you cite the ASCL entry.