New XML::LibXML input callbacks API

The latest version of the XML::LibXML libraries have changed the way input callbacks are registered. These are the functions you can provide to override how URLs are resolved for XIncluded files, DTDs, etc. I'm using this in Daizu in the parse_xhtml_content function so that XIncluded files in XHTML articles are read from the database, if appropriate.

(Update: The parse_xhtml_content function no longer exists as of Daizu 0.2. The XML parsing is now done in the XHTMLArticle plugin, but the XInclude expansion I talk about here is done in the expand_xinclude function.)

Here's the code I've had until just now to set up the callbacks:

$parser->callbacks(
    \&_match_uri,
    sub { _open_uri($cms, $wc_id, @_) },
    \&_read_uri,
    \&_close_uri,
);

As of version 1.59 of the XML::LibXML Perl bindings there are two changes. Firstly, values returned from the open callback have to be references. This actually caught me out slightly because my test suite was returning a string to check that it would be passed to the read callback, which of course it wasn't anymore. If you adjust your callback functions to always use references then they should work, and still be compatible with earlier LibXML versions.

They've also added a new interface for configuring callbacks. Apparently the old code set this stuff globally, so you could be screwed if it was running in a mod_perl environment, but this new interface called XML::LibXML::InputCallback. The callback functions don't need to change—apart from as noted above—but the code that sets them now looks like this:

my $input_callbacks = XML::LibXML::InputCallback->new;
$input_callbacks->register_callbacks([
    \&_match_uri,
    sub { _open_uri($cms, $wc_id, @_) },
    \&_read_uri,
    \&_close_uri,
]);
$parser->input_callbacks($input_callbacks);

The new interface allows you to add multiple groups of callback functions on some kind of stack, and then pop them off later. I suppose I could use this to provide a way for Daizu plugins to register their own sets of callbacks. Perhaps a plugin to provide more controlled access to files from the database/Subversion repository, so you could XInclude a file with a particular path from a particular revision. Probably not all that useful, but rather cool.

Since Daizu is new and experimental, I've decided to require version 1.59 of the XML::LibXML bindings. By the time anyone is actually deploying this thing, if ever, that shouldn't be too bleeding edge to be a problem.

< Tracking branches | Character encodings in Perl >