[英]How to find child elements of a specified parent using 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
重新創建它。 但是,很不幸,我停留在第一行。 這僅關注第一行:
我讀這是
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
具有值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::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' );
實際上,我收到此錯誤: “無法在屬性上創建新的名稱空間!” 這似乎與方法名稱的含義及其在文檔上的描述矛盾: “創建綁定到名稱空間的屬性”。
所以,我想,好的,我不能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.