Вопрос по xml, perl – Выражение xpath в findnodes (), возвращающее пустой список узлов

5

XML:

<zoo xmlns="http://www.zoo.com" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://www.zoo.com employee.xsd">

<area id="1" posizione="nord" nome="scimmie">
    <animale>
        <nome>Gigi</nome>
        <sesso>Male</sesso>
        <eta>3</eta>
    </animale>

    <animale>
        <nome>Gigia</nome>
        <sesso>Female</sesso>
        <eta>2</eta>
    </animale>
</area>

<area id="2" posizione="nord" nome="giraffe">
    <animale>
        <nome>Giro</nome>
        <sesso>Male</sesso>
        <eta>6</eta>
    </animale>

    <animale>
        <nome>Gira</nome>
        <sesso>Female</sesso>
        <eta>5</eta>
    </animale>
</area>
</zoo>

код:

my $parser = XML::LibXML->new;
my $doc = $parser->parse_file("../xml/animals.xml");
my $root = $doc->getDocumentElement();

my $new_animal = $doc->createElement("animale");

my $name_element = $doc->createElement("nome");
$name_element->appendTextNode($name);

my $gender_element = $doc->createElement("sesso");
$gender_element->appendTextNode($gender);

my $age_element = $doc->createElement("eta");
$age_element->appendTextNode($age);

$new_animal->appendChild($name_element);
$new_animal->appendChild($gender_element);
$new_animal->appendChild($age_element);

my $area_element = $root -> findnodes("//area[\@id=$area]")->get_node(1);

$area_element->appendChild($new_animal);

$ area - это идентификатор области (обычно 1 сейчас, когда я тестирую)

моя цель - создать новое животное и добавить его в нужную область

но у меня проблема в том что иструкция

    my $area_element = $root -> findnodes("//area[\@id=$area]")->get_node(1);

не сработает, потому что $ area_element имеет значение undef, поскольку findnodes всегда возвращает пустой список узлов (проверяется печать size ()).

Я думаю, что проблема заключается в выражении xpath внутри findnodes, но я не могу понять, в чем дело, я использую это же выражение с другой библиотекой (XML :: XPath), и она работает.

Что не так?

Ваш Ответ

2   ответа
4

http://www.zoo.com, так что вы должны указать это в выражениях XPath для узлов, которые нужно подобрать.

Способ сделать это - объявитьXML::LibXML::XPathContext объект, который присваивает имя этому пространству имен. Затем имя можно использовать в выражениях XPath для доступа к узлам.

Если ты пишешь

my $xpc = XML::LibXML::XPathContext->new;
$xpc->registerNs('zoo', 'http://www.zoo.com');

теперь у вас есть контекст, в котором пространство имен XML по умолчанию называетсяzoo, Теперь вы можете написать

my $area_element = $xpc->findnodes("//zoo:area[\@id=$area]", $doc)->get_node(1);

и вы найдете правильный<area> элемент.

видел ваше изменение в ответе (добавлено & quot ;, $ doc & quot;), теперь, похоже, оно работает, я тестирую его qwertoyo
Я пытался с вашим кодом, но я получаю это: ---------- Ошибка программного обеспечения: XPathContext: потерян текущий узел в /Users/toyo/Sites/zoo/cgi-bin/_nuovo_animale.cgi строка 76 - ------- строка 76: my $ area_element = $ xpc - & gt; findnodes (& Quot; // зоопарка: площадь [\ @ J = $ области] & Quot;) - & GT; get_node (1); qwertoyo
@qwertoyo, попробуйте проще:my ($area_element) = $xpc->findnodes("//zoo:area[\@id=$area]", $doc);
Сработало, спасибо;) qwertoyo
@ qwertoyo, это новая проблема, и здесь действительно нет места для ее обсуждения. Пожалуйста, задайте новый вопрос и предоставьте минимальный исполняемый код, необходимый для демонстрации проблемы.
-2

<zoo xmlns:zoo="http://www.zoo.com" или т.п.

<foo xmlns="..."> а также<bar:foo xmlns:bar="..."> являются правильными и эквивалентными (при условии, что дети имитируют отсутствие / наличие префикса). Пространство имен, определенное в<foo xmlns:bar="..."> никогда не используется, поэтому ваш совет неверен.
Неправильный ответ. В объявлении пространства имен нет ничего плохого. Downvoting.
xmlns="http://www.zoo.com" без идентификатора пространства имен просто связываетdefault пространство имен, то есть пространство имен для всех элементов, которые не имеют префикса. Если нет определения пространства имен по умолчанию, тогда это как объявлениеxmlns="" был использован.

Похожие вопросы