Re: Using XML::LibXML::SAX::Parser as replacement for XML::LibXML::SAX::Generator
Robin Berjon <[email protected]>
| Newsgroups | gmane.comp.lang.perl.xml |
|---|---|
| Message-ID | <[email protected]> |
On Apr 2, 2010, at 21:54 , Kjetil Kjernsmo wrote:
> On Thursday 1. April 2010 11:57:59 Robin Berjon wrote:
>> Not just XSLT in fact, you can also use XPath and modify the DOM in
>> place with Perl, for some uses it can be a lot simpler.
>
> OK. I've written a few thousand lines of XSLT, and has had many hours of
> pain in unspeakable places, so I figured I'd try a different XML technology
> this time.
Heh. Possibly the hardest thing in XML is picking the right tool for any given task. There are cases in which using XSLT is a PITA, and others where it shines; and the same applies to pretty much anything else.
It does indeed look like your case requires more processing than I'd be happy to do with XSLT, so something Perl-based sounds good.
> Basically, I generate a SPARQL query based on the input document, run that
> query, get a table back, and then reinsert the values from that table into
> the result document. So, the idea here is that I need to do some variable
> substitutions. That's why I felt XSLT was the wrong tool for the job, I
> would have to do that programmatically, so a static stylesheet wouldn't do.
> Perhaps I could do something clever with a function, though...
Actually, the primary reason why XSLT is a bad match is mostly because it doesn't have any SPARQL support, and limited HTTP support (only the simplest GETs). If you were getting information in XML from given URIs in the source document, you could rather easily use XSLT for this task (with the document() function).
>> Kjetil: do you have some code to show us so we could advise options?
>
> Sure! My RDF::RDFa::Template module (not yet on CPAN) is the example :-)
> More specifically, it would be great if you had a look at the current SAX
> Filter:
> http://svn.kjernsmo.net/RDF-RDFa-Template/trunk/lib/RDF/RDFa/Template/SAXFilter.pm
So, this is not at all a complete port of your code, it's just an example of how it can be done with Perl using XPath to power the transformations:
package RDF::RDFa::Template::Munger;
use warnings;
use strict;
use constant RAT_NS => "http://www.kjetil.kjernsmo.net/software/rat/xmlns";
use constant G_NS => "http://example.org/graph#";
use XML::LibXML::XPathContext;
# $self is anything, $doc is an XML::LibXML Document, %opt should be obvious below
sub munge {
my ($self, $doc, %opt) = @_;
my $baseURI = $opt{BaseURI} || "./";
my $inGraph = 0;
my $curGraph = undef;
my $xc = XML::LibXML::XPathContext->new($doc);
$xc->registerNs(rat => RAT_NS);
$xc->registerNs(g => G_NS);
# delete attributes I don't like
for my $at (qw/doctype-system doctype-public/) {
$_->removeAttributeNS(RAT_NS, $at) for $xc->findnodes("//*[\@rat:$at]");
}
# get all the rat:graph and process them
my @rats = $xc->findnodes("//rat:graph");
for my $rat (@rats) {
# do some Semantic Magic
my $results = $self->sparqlSomething($rat->getAttributeNS(undef, "endpoint"), $rat->getAttributeNS(G, "graph"));
# get all the children of the curren rat:graph that have an about attribute, and expand the URI
my @abouts = $xc->findnodes(".//*[@about]", $rat);
for my $about (@abouts) {
if ($about->getAttributeNS(undef, "about") =~ m/^sub:(\w+)$/) {
my $uri = $self->give_me_a_uri($1);
$about->setAttributeNS(undef, "about", $uri);
}
}
# etc...
}
}
1;
I haven't tested it, or even tried to compile it, but hopefully it can give an idea. It's probably a lot easier to do it this way than with SAX.
> The
> three things I want to resolve before uploading to CPAN is this xmlns
> stripping problem,
Assuming your namespace declarations are all on the root element, that $doc holds the Document, and that the namespace isn't used by any attribute or element in the context (it would still work, but you'd be getting side-effects), the following should work:
my $root = $doc->documentElement;
for my $pfx (@prefixes_I_want_dead) {
$root->setNamespaceDeclURI($pfx, undef);
}
> the doctype declaration,
Still assuming $doc holds the Document, with $root from above, and $pubId and $sysId retrieved from the proper places:
$doc->setExternalSubset($doc->createExternalSubset($root->tagName, $pubId, $sysId));
> and finally, package a simple
> HTTP::Server::Simple script for people to try it out.
For that, you're on your own :)
--
Robin Berjon - http://berjon.com/
_______________________________________________
Perl-XML mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs