Eva*_*oll 2 xml perl xml-namespaces libxml2
我正在尝试用FOAF和Perl做一些事情.我对目前的解决方案不满意,我想自己动手.请不要参考除以外的任何模块XML::LibXML.
这里参考的是FOAF文件的片段
<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>
....
Run Code Online (Sandbox Code Playgroud)
现在,排除空白,我正在尝试重新创建它XML::LibXML.但是,我很遗憾地陷入了第一线.这只关注第一行:
我读到这个
RDF,在命名空间中rdf声明
rdf名称空间属性xmlnshttp://www.w3.org/1999/02/22-rdf-syntax-ns#rdfs名称空间属性xmlnshttp://www.w3.org/2000/01/rdf-schema#foaf名称空间属性xmlnshttp://xmlns.com/foaf/0.1/admin名称空间属性xmlnshttp://webns.net/mvcb/首先你需要一个元素rdf:RDF,这似乎很棘手.阅读我找到的文档,但这似乎没有做我想要的:XML::LibXML::DocumentcreateElementNS()
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"/>
Run Code Online (Sandbox Code Playgroud)
现在,我尝试createElement('rdf:RDF')它的工作原理!我得到了根元素rdf:RDF.这是我们应该如何创建根元素?我只是读错了XML吗?
现在,我需要创建属性(模式声明).我尝试了记录不佳的文件XML::LibXML::Document,createAttributeNS但它也没有用:
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' );
Run Code Online (Sandbox Code Playgroud)
实际上我得到了这个错误:"无法在属性上创建新的命名空间!" 这似乎与方法名称所暗示的相矛盾,以及它对文档的描述:"创建绑定到命名空间的属性".
所以,我想,好吧我做不到create的attributeNS,也许我可以set一个attributeNS接着.而且,我继续下一记录的方法这个时候XML::LibXML::Element,看起来适用: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' );
Run Code Online (Sandbox Code Playgroud)
这次我得到一个不同的错误:"坏ns属性!" .所以我回顾了一些测试,并发现这个需要一个属性键值而不是命名空间声明来做我想要的..这不是我想要的.
以下是一些可能的组合和输出:
$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"/>
Run Code Online (Sandbox Code Playgroud)
尽管我知道它们与XML命名空间有关,但似乎没有任何*NS方法可以工作.最后,我尝试非NS版本:
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#"/>
Run Code Online (Sandbox Code Playgroud)
我感觉到这种可怕的感觉我没有做到这一点.我做对了吗?如何使用DOM(不使用appendTextChild)添加子元素?
这整个XML::LibXML是非常不良记录,但似乎是最好的Perl所提供的快速XML创建一个DOM.
从内存(并编辑正确性),你这样做:
use XML::LibXML;
my $doc = XML::LibXML::Document->new( '1.0', 'UTF-8' );
my $foaf = $doc->createElementNS( 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'RDF' );
$doc->setDocumentElement( $foaf );
$foaf->setNamespace( 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' , 'rdf', 1 );
$foaf->setNamespace( 'http://www.w3.org/2000/01/rdf-schema#' , 'rdfs', 0 );
$foaf->setNamespace( 'http://xmlns.com/foaf/0.1/' , 'foaf', 0 );
$foaf->setNamespace( 'http://webns.net/mvcb/' , 'admin', 0 );
my $node = $doc->createElementNS( 'http://xmlns.com/foaf/0.1/', 'Person');
$foaf->appendChild($node);
$node->setAttributeNS( 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'ID', 'me');
my $node2 = $doc->createElementNS( 'http://xmlns.com/foaf/0.1/', 'name');
$node2->appendTextNode('Evan Carroll');
$node->appendChild($node2);
print $doc->toString;
Run Code Online (Sandbox Code Playgroud)
也就是说,您始终需要使用命名空间URI并将命名空间声明添加到根节点(这是您指定命名空间前缀的唯一位置 - 我认为如果您不提供它们,libxml将创建自己的前缀).从维护的角度来看,把它们放在一些变量中显然是明智的.
只要您不需要内存中的DOM来识别名称空间,您的最终(非命名空间)版本就会起作用.这就像1级DOM不了解名称空间一样:您可以将名称空间视为普通属性,文档仍然可以很好地形成(但可能没有很好地形成名称空间).
这有点起作用,但名称空间前缀不是给定的.对此的讨论在别处.