Используя perl XML::LibXML, как вы используете префиксы 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>
Есть идеи? Я считаю, что это технически правильно в любом случае, но я бы предпочел не зависеть от других людей, знающих об этом. Я сам этого не знал вчера.
1 ответ
Короткий ответ: если у вас уже есть namespaceURI и объявлен префикс, вы можете указать полное имя (то есть префикс: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. Для достижения этой цели вводится концепция namespaceURI (nsURI) и механизм указания того, какой nsURI относится к каким элементам и атрибутам в XML-документе, встраивается в XML. Для этого используется тот факт, что имена атрибутов, начинающиеся с "xml" , зарезервированы, что позволяет использовать специальное имя атрибута (xmlns) без риска столкновения.
Общая идея состоит в том, что можно связать каждый словарь, используемый в документе XML, с уникальным nsURI (который рассматривается как непрозрачная строка). Элемент head в словаре XHTML полностью определяется {{ http://www.w3.org/1999/xhtml':' head '}, и это явно отличается от головы в (гипотетической) анатомии-ML {'мой-загримированный-URI':'голова'}. Вопрос заключается в том, как встроить nsURI в документ XML и как связать их с именами элементов.
Один из способов установить связь между nsURI и именем элемента - добавить атрибут xmlns к элементу. Например:
<name xmlns="http://xmlns.com/foaf/0.1/">Evan Carroll</name>
говорит, что имя находится в пространстве имен http://xmlns.com/foaf/0.1/. Объявления пространства имен наследуются детьми, поэтому "age" находится в том же пространстве имен:
<name xmlns="http://xmlns.com/foaf/0.1/">Evan Carroll<age years='21'/></name>
Это может хорошо работать и быть довольно компактным. Однако, это не работает для атрибутов и может запутаться, если многим узлам-родителям нужно изменить пространство имен от их общего родителя. Для решения обеих этих проблем введено NamespacePrefix (nsPrefix). Это дает двоеточие особый смысл. Идея состоит в том, чтобы связать nsURI со строкой, которая используется в текущем документе. Это не имеет никакого особого значения вне документа и не должно определяться словарем (но иногда это обсуждение в другом месте). Особенно часто все nsURI объявляются в корневом элементе. Синтаксис должен объявить пространство имен таким образом:
xmlns:prefix="http://xmlns.com/foaf/0.1/"
и используйте его в именах атрибутов и элементов, добавив nsPrefix к имени:
<prefix:name prefix:attribute='value'/>
Поскольку точное значение nsPrefixes не должно иметь значения, API, как правило, не облегчают доступ к ним / их установку (хороший пример - Xpath). Наличие пространств имен приводит к некоторым ограничениям в документе, которые следует рассматривать как ошибки, например, использование префикса, который не определен. Но такой документ может быть правильно сформирован в соответствии со спецификацией XML (помните, что пространства имен модифицированы). Вы можете охарактеризовать такой документ как "не правильно сформированное пространство имен".
Разбор документа, использующего пространства имен, с помощью синтаксического анализатора, который ничего не знает о пространствах имен, очевидно, проще, если вы знаете заранее используемые префиксы пространства имен. Но это довольно хрупкое решение, так как префиксы пространства имен могут изменяться в нечетных местах, поскольку документ XML неоднократно обрабатывается. Большинство парсеров осведомлены о пространстве имен.