2017-02-09 3 views
4

У меня есть следующий XML:В Perl с использованием Mojo :: DOM в режиме XML, как я могу совместить содержимое субтитров?

<Product> 
    ... 
    <TitleDetail> 
     <TitleType>01</TitleType> 
     <TitleElement> 
     <TitleElementLevel>01</TitleElementLevel> 
     <TitleText>This is the title I'm looking for</TitleText> 
     </TitleElement> 
    </TitleDetail> 
    ... 
</Product> 

(Это ONIX, если вам интересно.)

Я хочу, чтобы извлечь название, тип 01. Я пробовал:

say $dom->at('TitleDetail[TitleType="01"] > TitleElement > TitleText') 

но это не работает. Похоже, что синтаксис tag[attr=value] действительно работает только для атрибутов.

Есть ли простой способ сделать то, что я хочу?

+0

Это была одна ошибка, да, использовать '/' вместо '>' как маркерный сепараторе ... – mscha

+2

'TitleDetail [TitleType = "01"]' [средства] (HTTP: // Mojolicious .org/perldoc/Mojo/DOM/CSS # SELECTORS) "* элемент' TitleDetail', значение атрибута 'TitleType' в точности равно' 01'. * «Очевидно, что неверно. К сожалению, вы не можете использовать один вызов для 'at', потому что подзапросы ограничены проверкой атрибутов, и ни один из селекторов не предоставляет средство проверки текста узла. – ikegami

ответ

5

Это можно сделать с помощью Mojo :: DOM, но он длинный. Несколько раз там есть Mojo :: Collections, поэтому вам нужно получить первый элемент.

use Mojo::DOM; 

my $dom = Mojo::DOM->new->xml(1)->parse($xml); 
say $dom->find("TitleType")->grep(sub{ $_->text eq "01"})->first 
    ->following("TitleElement")->first->at("TitleText")->text; 
+1

Спасибо! Я приму этот ответ, если в ближайшее время ничего не добьешься. Но я не буду использовать его; XML :: XPath в этом случае оказывается лучше. – mscha

+0

@mscha Я согласен с тем, что XML :: XPath лучше. Он выглядит более чистым, и, вероятно, он делает меньше работы, чтобы выполнить свою работу. – simbabque

5

Возможно, моя проблема в том, что я использую молоток, чтобы вставить винт ...

Я люблю Mojo :: DOM и его простота, но, возможно, это не так хорошо подходит для анализа структурированных XML, и я следует использовать XML :: XPath:

my $xp = XML::XPath->new(xml=>$xml); 
say $xp->findvalue('//TitleDetail[TitleType=01]/TitleElement/TitleText'); 

Это делает то, что мне нужно.

+0

Теперь просто переключитесь на XML :: LibXML (или XML :: Twig), и у вас есть электроинструмент для любого винта - как только вы заметили, что не настаиваете на молотке :) – zdim

+2

@zdim Не винт ... Mojo :: DOM может обрабатывать HTML и искаженный XML, в то время как эти модули не могут. : P – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot Правильно, спасибо, должен был сказать «идеальный винт». Кроме того, точка (с 'XML :: XPath'), похоже, просто подходит для' XPath', поэтому, возможно, мой комментарий полностью отключен. – zdim