Как использовать префиксы XML, а не атрибуты xmlns при использовании Perl XML :: LibXML?

Я полагаю, что этот вопрос мог быть ранее задан в 2006 году на другом сайте. Но мой текущий модуль записи XML / RDF (XML::LibXML 1.70) выводит пространства имен элементов в форме атрибутов xmlns. Это исключит людей, использующих парсеры, не поддерживающие пространство имен, которые просто просматривают 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
Вы «с» Эваном, который задал вопрос, или Эваном, который сделал первый комментарий? Я не уверен, кого вы считаете «неправильным», но есть (иногда) разумные причины для жесткого контроля над объявлениями пространств имен. Это может быть достигнуто с помощью привязок XML :: LibXML к DOM. Насколько я понимаю, ничто не «сломается» при осуществлении этого контроля.   -  person Andrew Walker    schedule 02.03.2010
comment
@reinierpost, это было мое замешательство: (а) Я не хочу зависеть от ботов foaf, поддерживающих XML-NS. (б) я не знал или визуально не любил избыточные атрибуты xmlns, и (в) я не знал, что и 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)


Короткий ответ заключается в том, что если у вас уже есть объявленный namespaceURI и префикс, вы можете указать полное имя (т.е. 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-документ. Для этого вводится концепция namespaceURI (nsURI) и механизм указания того, какой nsURI относится к каким элементам и атрибутам в XML-документе, модифицируется в XML. Для этого используется тот факт, что имена атрибутов, начинающиеся с 'xml' зарезервированы, что позволяет использовать специальное имя атрибута (xmlns) без риска столкновения.

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

Один из способов установить связь между nsURI и именем элемента - добавить к элементу атрибут xmlns. Например:

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

говорит, что '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-документа. Большинство парсеров осведомлены о пространстве имен.

person Andrew Walker    schedule 02.03.2010
comment
Благодаря тонну. Я очень ценю твои ответы. - person Evan Carroll; 02.03.2010