I'm trying to do some stuff with FOAF and Perl. I'm unhappy with the current solutions and I want to roll my own. Please do not reference any module other than XML::LibXML
.
For reference here is a snippet from a FOAF file
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:admin="http://webns.net/mvcb/">
<foaf:Person rdf:ID="me">
<foaf:name>Evan Carroll</foaf:name>
....
Now, excluding whitespace, I'm trying to recreate this with XML::LibXML
. However, I'm unfortunately stuck on the very first line. This just focuses on the first line:
I read this to be
- element
RDF
, in namespacerdf
declares- attribute
rdf
in namespacexmlns
with valuehttp://www.w3.org/1999/02/22-rdf-syntax-ns#
- attribute
rdfs
in namespacexmlns
with valuehttp://www.w3.org/2000/01/rdf-schema#
- attribute
foaf
in namespacexmlns
with valuehttp://xmlns.com/foaf/0.1/
- attribute
admin
in namespacexmlns
with valuehttp://webns.net/mvcb/
- attribute
Firstly you need an element rdf:RDF
, this seems to be tricky. Reading the doc for XML::LibXML::Document
I found createElementNS()
but this doesn't seem to do what I want:
use XML::LibXML;
my $doc = XML::LibXML::Document->new( '1.0', 'UTF-8' );
my $foaf = $doc->createElementNS( 'RDF', 'rdf' );
print $foaf->toString; # prints <rdf xmlns="RDF"/>
Now, I try createElement('rdf:RDF')
this works! I got the root element rdf:RDF
. Is this how we're supposed to create root elements? Am I just reading XML wrong?
Now, I need to create the attributes (schema declarations). I tried the poorly documented XML::LibXML::Document
's createAttributeNS
this didn't work either:
my $doc = XML::LibXML::Document->new( '1.0', 'UTF-8' );
my $foaf = $doc->createElement( 'rdf:RDF' );
$doc->createAttributeNS( 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf' );
In fact it errored with "can't create a new namespace on an attribute!" Which seems to be exactly what the name implies, and the description on the docs "Creates an Attribute bound to a namespace."
So, I figure, ok I can't create
an attributeNS
, maybe I can set
an attributeNS
then. And, I proceed with the next documented method this time on XML::LibXML::Element
that looks applicable: setAttributeNS
.
my $doc = XML::LibXML::Document->new( '1.0', 'UTF-8' );
my $foaf = $doc->createElement( 'rdf:RDF' );
$foaf->setAttributeNS( 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf' );
This time I get a different error: bad ns attribute!. So I review some of the tests, and find this one requires a attribute key-value other than the namespace declairation to do what I want.. Which isn't what I want.
Here are some possible combinations and outputs:
$foaf->setAttributeNS( http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf:', undef );
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" rdf:=""/>
$foaf->setAttributeNS( 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf:foo', 'bar' );
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" rdf:foo="bar"/>
It seems nothing with *NS wants to work, even though I know these are XML namespaces. Finally, I try the non-NS version:
my $doc = XML::LibXML::Document->new( '1.0', 'UTF-8' );
my $foaf = $doc->createElement( 'rdf:RDF' );
$foaf->setAttribute( 'xmlns:rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' );
print $foaf->toString; # <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
I get this horrible feeling that I'm not doing this right. Did I do this right? How do I add a child Element with the DOM (not using appendTextChild
)?
This whole XML::LibXML
is very poorly documented but seems to be the best Perl has to offer for fast XML creation w/ a DOM.