簡體   English   中英

使用XML :: LibXML:如何創建名稱空間和子元素並使它們一起工作?

[英]Using XML::LibXML: How do I create namespaces and child elements and make them work together?

我正在嘗試使用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. 名稱空間xmlns rdf屬性,其值是http://www.w3.org/1999/02/22-rdf-syntax-ns#
    2. 名稱空間xmlns屬性rdfs值為http://www.w3.org/2000/01/rdf-schema#
    3. 名稱空間xmlns屬性foaf值為http://xmlns.com/foaf/0.1/
    4. 名稱空間xmlns具有值http://webns.net/mvcb/屬性admin

首先,您需要一個元素rdf:RDF ,這似乎很棘手。 閱讀文檔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' );

實際上,我收到此錯誤: “無法在屬性上創建新的名稱空間!” 這似乎與方法名稱的含義及其在文檔上的描述矛盾: “創建綁定到名稱空間的屬性”。

所以,我想,好的,我不能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' );

這次我得到了另一個錯誤: “錯誤的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所提供的快速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;

也就是說,您始終需要使用名稱空間URI並將名稱空間聲明添加到您的根節點(這是您指定名稱空間前綴的唯一位置-我認為libxml將在不提供前綴的情況下發明自己的前綴)。 從維護的角度來看,將這些變量放入一些變量中顯然是明智的。

只要您不需要內存中的DOM即可知道名稱空間,那么最終的(非命名空間)版本將起作用。 這適用於1級DOM不了解名稱空間的情況:您可以將名稱空間視為普通屬性,並且文檔仍會格式正確(但名稱空間格式可能不正確)。

這一點可行,但是名稱空間前綴不是給定的。 關於此的討論在其他地方

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM