2

我正在尝试用 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>
....

现在,不包括空格,我正在尝试用XML::LibXML. 但是,不幸的是,我被困在了第一行。这仅关注第一行:

我读到这是

  1. 元素RDF,在命名空间中rdf声明
    1. rdf命名空间xmlns中具有值的属性http://www.w3.org/1999/02/22-rdf-syntax-ns#
    2. rdfs命名空间xmlns中具有值的属性http://www.w3.org/2000/01/rdf-schema#
    3. foaf命名空间xmlns中具有值的属性http://xmlns.com/foaf/0.1/
    4. admin命名空间xmlns中具有值的属性http://webns.net/mvcb/

首先你需要一个 element 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"/>

现在,我尝试createElement('rdf:RDF')并且它有效!我得到了根元素rdf:RDF。这就是我们应该创建根元素的方式吗?我只是读错了 XML 吗?

现在,我需要创建属性(模式声明)。我尝试了记录不佳XML::LibXML::Document的 'screateAttributeNS但它也不起作用:

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' );

事实上我得到了这个错误:“不能在属性上创建一个新的命名空间!” 这似乎与方法名称的含义以及文档上的描述相矛盾:“创建绑定到命名空间的属性”。

所以,我想,好吧,我不能createattributeNS也许我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' );

这次我得到一个不同的错误:“错误的 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"/>

似乎 *NS 方法都不起作用,即使我知道它们与 XML 命名空间有关。最后,我尝试了非 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#"/>

我有一种可怕的感觉,我做的不对。我做对了吗?如何使用 DOM 添加子元素(不使用appendTextChild)?

整个文档XML::LibXML的文档很差,但似乎是 Perl 为使用 DOM 快速创建 XML 提供的最好的东西。

4

1 回答 1

6

从记忆中(并为正确性而编辑),您可以这样做:

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;

也就是说,您总是需要使用命名空间 URI 并将命名空间声明添加到您的根节点(这是您指定命名空间前缀的唯一地方 - 如果您不提供它们,我认为 libxml 会发明自己的前缀)。从维护的角度来看,将这些放在一些变量中显然是明智的。

只要您不需要内存中的 DOM 来识别命名空间,您的最终(非命名空间)版本就可以工作。这是因为 1 级 DOM 不了解名称空间:您可以将名称空间视为普通属性,并且文档仍然是格式良好的(但可能不是名称空间格式正确)。

这在一定程度上有效,但命名空间前缀不是给定的。对此的讨论在别处

于 2010-03-01T21:10:33.133 回答