Използвайки XML::LibXML на perl, как използвате XML префикси, а не xmlns атрибути?

Вярвам, че този въпрос може да е бил задаван преди това през 2006 г. на друг сайт. Но текущият ми XML/RDF писател (XML::LibXML 1.70) извежда пространства от имена на елементи под формата на xmlns атрибути. Това ще изключи хора, използващи парсери без пространство на имена, които просто правят look_down за foaf:Person. Чудя се дали някой знае лесен начин в perl да постигне това, първо, с XML::LibXML. Или чрез различни средства.

Възли като този:

  <Person xmlns="http://xmlns.com/foaf/0.1/" rdf:ID="me"/>

И този:

  <name xmlns="http://xmlns.com/foaf/0.1/">Evan Carroll</name>

Наистина трябва да изглежда така:

  <foaf:Person rdf:ID="me"/>
  <foaf:name>Evan Carroll</name>

Някакви идеи? Вярвам, че е технически правилно и в двата случая, но бих предпочел да не разчитам други хора да знаят това. Аз самият не го знаех вчера.


person Evan Carroll    schedule 01.03.2010    source източник
comment
Дори не съм сигурен, че това е правилно. Тук съм напълно объркан.   -  person Evan Carroll    schedule 02.03.2010
comment
Аз съм с Евън. Грешите - опитвате се да превърнете валиден FOAF документ в нещо, което не е. Хората, които използват XML парсери, които не познават пространството на имената, не са ваш проблем и ако е така, не трябва да се опитвате да го поправите, като разбивате нещата и от своя страна.   -  person reinierpost    schedule 02.03.2010
comment
Вие сте „с“ Евън, който зададе въпроса, или Еван, който направи първия коментар? Не съм сигурен кой смятате за „грешно“, но (понякога) има разумни причини за строг контрол върху декларациите на пространството от имена. Това може да се постигне с DOM обвързванията на XML::LibXML. Доколкото виждам, нищо не се „счупва“ от упражняването на този контрол.   -  person Andrew Walker    schedule 02.03.2010
comment
@reinierpost, това беше моето объркване: (a) Не искам да завися от XML-NS, запознати с foaf ботове. (b) Не знаех или визуално не харесвах излишните атрибути xmlns и (c) не знаех, че и foaf:, и xmlns= могат да бъдат изключени и все още да имат работещ документ на foaf.   -  person Evan Carroll    schedule 02.03.2010
comment
Подкрепям коментатора Евън, че никога не трябва да променяте пространствата от имена на елементите, но вашият отговор прави точно това, което питащият Евън иска.   -  person reinierpost    schedule 03.03.2010
comment
Няма коментатор Евън, който бях аз, питащият, заявяващ, че съм объркан, защото не бях сигурен, че <foaf:name>foo</name> е същото нещо като <name xmlns="http://foaf..">foo</name> и нещо повече, същото като <foaf:Person><name>foo</name></Person>   -  person Evan Carroll    schedule 03.03.2010


Отговори (1)


Краткият отговор е, че ако вече имате деклариран URI за пространство от имена и префикс, можете да посочите квалифицираното име (т.е. prefix:localName) като име на елемент и това ще накара XML::LibXML да избегне повторното деклариране на пространството от имена. И така, модифицирането на кода от последния въпрос дава следното, което използва желаните префикси на пространството от имена:

#! /usr/bin/perl 
use warnings;
use strict;
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/', 'foaf: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/', 'foaf:name');
$node2->appendTextNode('Evan Carroll');
$node->appendChild($node2);
print $doc->toString;

Може би все пак си струва да се опитате да прегледате какво се случва. XML пространства от имена съществуват, за да позволят множество речници да се използват заедно в едно и също XML документ. За да се постигне това, се въвежда концепцията за URI на пространството от имена (nsURI) и механизъм за указване кой nsURI се отнася до кои елементи и атрибути в XML документ се преоборудва върху XML. За целта се използва фактът, че имената на атрибутите започват с 'xml' са запазени, което позволява използването на специално име на атрибут (xmlns) без риск от сблъсък.

Общата идея е, че е възможно да се свърже всеки речник, използван в XML документ, с уникален nsURI (който се третира като непрозрачен низ). Главният елемент в XHTML речника е напълно дефиниран от {'http://www.w3.org/1999/xhtml':'head'} и това е ясно различно от главата в (хипотетична) анатомия-ML {'my-made-up-URI':'head'}. Проблемът е как да вградите nsURI(ите) в XML документ и как да ги свържете с имената на елементите.

Един от начините да направите връзка между nsURI и име на елемент е да добавите атрибута xmlns към елемента. Например:

<name xmlns="http://xmlns.com/foaf/0.1/">Evan Carroll</name>

казва, че „име“ е в „http://xmlns.com/foaf/0.1/ ' пространство от имена. Декларациите за пространство от имена се наследяват от деца, така че „възраст“ е в същото пространство от имена:

<name xmlns="http://xmlns.com/foaf/0.1/">Evan Carroll<age years='21'/></name>

Това може да работи добре и да бъде доста компактно. Това обаче не работи за атрибути и може да стане объркващо, ако много братски възли трябва да променят пространството на имената от техния общ родител. За справяне с двата проблема се въвежда Namespace Prefix (nsPrefix). Това придава на дебелото черво специално значение. Идеята е да свържете nsURI към низ, който се използва в текущия документ. Това няма специално значение извън документа и не трябва да се уточнява от речника (но понякога е така, дискусия за другаде). Особено обичайно е всички nsURI да бъдат декларирани в основния елемент. Синтаксисът е да декларирате пространството от имена по следния начин:

xmlns:prefix="http://xmlns.com/foaf/0.1/"

и го използвайте в имена на атрибути и елементи, като добавите nsPrefix към името:

<prefix:name prefix:attribute='value'/>

Тъй като точната стойност на nsPrefixes не би трябвало да има значение, API обикновено не правят достъпа/настройката им много лесен (Xpath е добър пример). Наличието на пространства от имена води до някои ограничения върху документа, които трябва да се третират като грешки, използването на префикс, който не е дефиниран, е пример. Но такъв документ може да бъде добре оформен според XML спецификацията (не забравяйте, че пространствата от имена са преоборудвани). Можете да опишете такъв документ като „не е добре оформено пространство от имена“.

Анализирането на документ, който използва пространства от имена с анализатор, който не знае нищо за пространствата от имена, очевидно е по-лесно, ако знаете предварително използваните префикси на пространството от имена. Но това е доста крехко решение, тъй като префиксите на пространството от имена могат да се променят на странни места, тъй като XML документ се обработва многократно. Повечето анализатори са наясно с пространството на имената.

person Andrew Walker    schedule 02.03.2010
comment
Благодаря много. Наистина оценявам отговорите ви. - person Evan Carroll; 02.03.2010