2013-02-09 3 views
0

Я пытаюсь обновить содержимое элемента xml. Я использую XML :: LibXML и должен использовать эту библиотеку. Вот несколько примеров данных.Perl XML :: LibXML update contect

<data-table> 
    <data> 
     <number>1</number> 
     <letter>one</letter> 
    </data> 
    <data> 
     <number>2</number> 
     <letter>two</letter> 
    </data> 
</data-table> 

То, что я хотел бы сделать, это изменить содержание письма «Purple», если число равно 2. Тем не менее, я считаю, у меня проблема, обозначающая Xpath для его работы. Я получаю следующую ошибку

«Не удается найти метод объекта„УстановитьДанные“с помощью пакета„XML :: Libxml :: NodeList“в»

Я боролся с этим в течение нескольких дней, так что любая помощь значительно оценили.

use XML::LibXML; 
    my $p = XML::LibXML->new; 
    my $d = $p->parse_fh(\*DATA); 
    for my $node ($d->findnodes('//data-table/data')) 
    { 
     for my $childNode ($node->findnodes('./number/text()')) 
     { 
      if($childNode->textContent() == '1') 
      { # here is where the problem is! 
      my $changeNumerNode = $node->findnodes('./letter/text()'); 
      $changeNumerNode->setData("Purple"); 
      } 
     } 
    } 
    print $d->toString; 

    __DATA__ 
    <data-table> 
     <data> 
     <number>1</number> 
     <letter>one</letter> 
     </data> 
     <data> 
     <number>2</number> 
     <letter>two</letter> 
     </data> 
    </data-table> 
+0

'findnodes' не возвращает узел. Он возвращает список узлов или NodeList. См. Ответ на связанный вопрос, как это сделать. – ikegami

+0

спасибо. Я видел это в своих поисках. но я тоже не могу удалить узел. Я понимаю, что findnodes не возвращает узел, но я зацикливаю узлы, как только я получу один, почему я не могу выполнять на нем действия? Это та часть, которую я не понимаю. Или правильный способ сделать это в первую очередь. Так я должен удалить все дочерние узлы , когда я нашел совпадение, а затем воссоздал все дочерние узлы ? это было бы неэффективно по моему сценарию. – ScottEdge

+0

Вы, кажется, пропустили, что связанное сообщение показывает, как получить узел – ikegami

ответ

2

findnodes не возвращает узел. Он возвращает список узлов или :: NodeList. Вы можете заставить его вернуть список и вернуть первый узел.

for my $node ($d->findnodes('//data-table/data')) 
{ 
    my ($number_node) = $node->findnodes('number') 
     or next; 
    $number_node->textContent() eq '1' 
     or next; 
    my ($letter_text) = $node->findnodes('letter/text()') 
     or next; 
    $letter_text->setData('Purple'); 
} 

(Как вы можете видеть, я снял чистое использование шума ./.)

Вы можете даже использовать

for my $letter_text ($d->findnodes(
    '//data-table/data[number/text()="1"]/letter/text()')) 
{ 
    $letter_text->setData('Purple'); 
} 
+0

. Я благодарен за этот ответ, но разочарован тем, как долго я читал документацию и примеры, но не думал, чтобы это было похоже на ваш второй пример. – ScottEdge

+0

вы взяли 12 строк кода, которые у меня были, и превратили их в 6. – ScottEdge

+0

XML :: LibXML не документирует XPaths. Я действительно называю это 2 или 3 строками. – ikegami