gpt4 book ai didi

xml - 使用 XML::LibXML:如何创建 namespace 和子元素并使它们协同工作?

转载 作者:数据小太阳 更新时间:2023-10-29 02:55:19 26 4
gpt4 key购买 nike

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

首先你需要一个元素rdf:RDF,这看起来有点棘手。阅读documentation对于 XML::LibXML::Document 我找到了 createElementNS() 但这似乎没有达到我想要的效果:

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::DocumentcreateAttributeNS 但它也不起作用:

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

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

所以,我想,好吧,我不能创建一个attributeNS,也许我可以设置一个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 属性!”。因此,我查看了一些测试,发现这个测试需要 namespace 声明以外的属性键值来执行我想要的操作。这不是我想要的。

以下是一些可能的组合和输出:

$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 所提供的最好的。

最佳答案

根据内存(并为正确性进行了编辑),您可以这样做:

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 不需要命名空间感知,您的最终(非命名空间)版本就可以使用。这是因为 Level 1 DOM 不知道 namespace :您可以将 namespace 视为普通属性,并且文档仍将是格式正确的(但可能不是格式正确的 namespace )。

这在一定程度上起作用,但 namespace 前缀不是给定的。对此的讨论 is elsewhere .

关于xml - 使用 XML::LibXML:如何创建 namespace 和子元素并使它们协同工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2358635/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com