2013-07-21 2 views
2

Я пытаюсь получить значение предыдущего узла в XPath, но я либо получаю дубликаты, либо нет значений.Как перейти к предыдущему родительскому узлу и получить значение элементов в XPath?

Код выглядит следующим образом:

use XML::LibXML; 

my %chapter_columns = (
    'Chapter_Id'   => '@id', 
    'Chapter_Title'  => 'book:locator[contains(@xlink:href, "format=epub")]/@xlink:title', 
    'Chapter_Doi_Prefix' => 'substring-before(book:meta/@doi,"/")', 
    'Book_Publisher'  => '//@publisherId', 
    'Book_Platform'  => '//@platform', 
); 

my $parser = XML::LibXML->new(); 
my $dom = $parser->parse_file("test.xml"); 
my $root = $dom->documentElement(); 
my $xpc = XML::LibXML::XPathContext->new($root); 

$xpc->registerNs('book', 'http://api.abc.org/Book/1.0/'); 
$xpc->registerNs('xlink', 'http://www.w3.org/1999/xlink'); 

foreach my $chapter_node ($xpc->findnodes('/book:bookResource/book:book/book:contents/book:chapter')) { 
    foreach my $col (qw/Chapter_Id Book_Publisher Book_Platform/) { 
    print $xpc->findvalue($chapter_columns{$col}, $chapter_node) . "\n"; 
    } 
} 

Я попытался получить значение "publisherId" и "платформы", используя // @ publisherId и // @ платформы. Они производят дублирующее значение для каждой книги. Я даже пытался забрать их «../../@publisherId»; но не получая никакой ценности.

Я не хочу менять xpath, определенный в цикле foreach, но намеренно перемещаться назад. Как я могу это достичь?

В результате я получаю:

Chapter_Id=bk444444ch1 
Book_Publisher=BKCBKC 
Book_Platform=ScienceScience 
Chapter_Id=bk444444ch2 
Book_Publisher=BKCBKC 
Book_Platform=ScienceScience 
Chapter_Id=bk444444ch1 
Book_Publisher=BKCBKC 
Book_Platform=ScienceScience 
Chapter_Id=bk444444ch2 
Book_Publisher=BKCBKC 
Book_Platform=ScienceScience 

в то время как я хочу:

Chapter_Id=bk444444ch1 
Book_Publisher=BKC 
Book_Platform=Science 
Chapter_Id=bk444444ch2 
Book_Publisher=BKC 
Book_Platform=Science 
Chapter_Id=bk444444ch1 
Book_Publisher=BKC 
Book_Platform=Science 
Chapter_Id=bk444444ch2 
Book_Publisher=BKC 
Book_Platform=Science 

XML-как показано ниже:

<?xml version="1.0" encoding="UTF-8"?> 
<book:bookResource xmlns:book="http://api.abc.org/Book/1.0/"> 
    <book:book> 
    <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
     4444-1000-17?releaseStatus=RELEASED" xlink:title="979-0-4444-1000-17" 
     xlink:type="locator"> 
    </book:locator> 
    <book:meta coverImage="/blank-cover.gif" publisherId="BKC" platform="Science" 
     doi="10.1088/bk444444" publicationDate="2016-12-01" issn="1111-222X" 
     collectionId="0001" lastModified="2013-07-05T09:03:40+05:30" releaseStatus="RELEASED"> 
    </book:meta> 
    <book:contents> 
     <book:chapter id="bk444444ch1" type="CHAPTER"> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch1?releaseStatus=RELEASED" 
      xlink:role="http://www.abc.org/roles/book-part-locator" xlink:title="Photonic" xlink:type="locator"> 
     </book:locator> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch1?releaseStatus=RELEASED&amp;format=pdf" 
      xlink:role="http://www.abc.org/roles/book-part-pdf-locator" xlink:title="Photonic 
      crystal light-emitting sources" xlink:type="locator"> 
     </book:locator> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch1?releaseStatus=RELEASED&amp;format=epub" 
      xlink:role="http://www.abc.org/roles/book-part-epub-locator" xlink:title="Photonic 
      crystal light-emitting sources" xlink:type="locator"> 
     </book:locator> 
     <book:meta doi="10.1088/bk444444ch1" firstPage="1-1" lastPage="1-118"> 
      <book:author givenName="J E" surname="Field"> 
      <book:affiliation xmlns:xlink="http://www.w3.org/1999/xlink" 
       xlink:href="bk444444ch1af1" xlink:role="http://www.abc.org/roles/affiliation-locator" 
       xlink:type="locator"> 
      </book:affiliation> 
      </book:author> 
      </book:meta> 
     </book:chapter> 
     <book:chapter id="bk444444ch2" type="CHAPTER"> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch2?releaseStatus=RELEASED" 
      xlink:role="http://www.abc.org/roles/book-part-locator" xlink:title="The effect of 
      long-range order on the elastic properties of Cu3Au" xlink:type="locator"> 
     </book:locator> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch2?releaseStatus=RELEASED&amp;format=pdf" 
      xlink:role="http://www.abc.org/roles/book-part-pdf-locator" xlink:title="The effect of 
      long-range order" xlink:type="locator"> 
     </book:locator> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch2?releaseStatus=RELEASED&amp;format=epub" 
      xlink:role="http://www.abc.org/roles/book-part-epub-locator" xlink:title="The effect of 
      long-range order" xlink:type="locator"> 
     </book:locator> 
     <book:meta doi="10.1088/bk444444ch2" firstPage="2-1" lastPage="2-35"> 
      <book:affiliation name="Department of Physics"> 
      <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="bk444444ch2af1" 
       xlink:role="http://www.abc.org/roles/affiliation-locator" xlink:type="locator"> 
      </book:locator> 
      </book:affiliation> 
     </book:meta> 
     </book:chapter> 
    </book:contents> 
    </book:book> 
    <book:book> 
    <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
     4444-1000-17?releaseStatus=RELEASED" xlink:title="979-0-4444-1000-17" 
     xlink:type="locator"> 
    </book:locator> 
    <book:meta coverImage="/blank-cover.gif" publisherId="BKC" platform="Science" 
     doi="10.1088/bk444444" publicationDate="2016-12-01" issn="1111-222X" 
     collectionId="0001" lastModified="2013-07-05T09:03:40+05:30" releaseStatus="RELEASED"> 
    </book:meta> 
    <book:contents> 
     <book:chapter id="bk444444ch1" type="CHAPTER"> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch1?releaseStatus=RELEASED" 
      xlink:title="Photonic crystal" xlink:type="locator"> 
     </book:locator> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch1?releaseStatus=RELEASED&amp;format=pdf" 
      xlink:title="Photonic 
      crystal light-emitting sources" xlink:type="locator"> 
     </book:locator> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch1?releaseStatus=RELEASED&amp;format=epub" xlink:title="Photonic 
      crystal" xlink:type="locator"> 
     </book:locator> 
     <book:meta doi="10.1088/bk444444ch1" firstPage="1-1" lastPage="1-118"> 
     </book:meta> 
     </book:chapter> 
     <book:chapter id="bk444444ch2" type="CHAPTER"> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch2?releaseStatus=RELEASED" 
      xlink:role="http://www.abc.org/roles/book-part-locator" xlink:title="The effect of 
      long-range order on the elastic properties of Cu3Au" xlink:type="locator"> 
     </book:locator> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch2?releaseStatus=RELEASED&amp;format=pdf" 
      xlink:role="http://www.abc.org/roles/book-part-pdf-locator" xlink:title="The effect of 
      long-range order on the elastic properties of Cu3Au" xlink:type="locator"> 
     </book:locator> 
     <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/book/isbn/979-0- 
      4444-1000-17/book-part/chapter/bk444444ch2?releaseStatus=RELEASED&amp;format=epub" 
      xlink:role="http://www.abc.org/roles/book-part-epub-locator" xlink:title="The effect of 
      long-range order on the elastic properties of Cu3Au" xlink:type="locator"> 
     </book:locator> 
     <book:meta doi="10.1088/bk444444ch2" firstPage="2-1" lastPage="2-35"> 
      <book:affiliation name="Department of Physics, University of San Salvador"> 
      <book:locator xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="bk444444ch2af1" 
       xlink:type="locator"> 
      </book:locator> 
      </book:affiliation> 
     </book:meta> 
     </book:chapter> 
    </book:contents> 
    </book:book> 
</book:bookResource> 

ответ

2

Выражение XPath как //@publisherId находит все publisherId атрибуты под корнем документа. (.//@publisherId находит все такие атрибуты, под текущим узлом, но это не то, что вы хотите, тоже.)

Вы должны использовать ancestor ось, чтобы найти book элемент, который содержит этот chapter, а затем получить доступ к атрибутам из meta Элемент, который является ребенком этой книги. Этот код работает отлично.

use strict; 
use warnings; 

use XML::LibXML; 

my %chapter_columns = (
    Chapter_Id   => '@id', 
    Chapter_Title  => 'book:locator[contains(@xlink:href, "format=epub")]/@xlink:title', 
    Chapter_Doi_Prefix => 'substring-before(book:meta/@doi,"/")', 
    Book_Publisher  => 'ancestor::book:book/book:meta/@publisherId', 
    Book_Platform  => 'ancestor::book:book/book:meta/@platform',      
); 

my $parser = XML::LibXML->new; 
my $dom = $parser->parse_file('test.xml'); 
my $xpc = XML::LibXML::XPathContext->new($dom); 

$xpc->registerNs('book', 'http://api.abc.org/Book/1.0/'); 
$xpc->registerNs('xlink', 'http://www.w3.org/1999/xlink'); 

my @chapters = $xpc->findnodes('/book:bookResource/book:book/book:contents/book:chapter'); 

foreach my $chapter (@chapters) { 
    foreach my $col(qw/Chapter_Id Book_Publisher Book_Platform/) { 
    printf "%s=%s\n", $col, $xpc->findvalue($chapter_columns{$col}, $chapter); 
    } 
    print "\n"; 
} 

Однако я хотел бы начать, находя все book элементов, сохранить атрибуты meta/@publisherId и meta/@platform, а затем перечислить все contents/chapter элементов для одной и той же книги. Как это

my @books = $xpc->findnodes('/book:bookResource/book:book'); 

for my $book (@books) { 

    my $publisher = $xpc->findvalue('book:meta/@publisherId', $book); 
    my $platform = $xpc->findvalue('book:meta/@platform', $book); 

    my @chapters = $xpc->findnodes('book:contents/book:chapter', $book); 
    for my $chapter (@chapters) { 

    my $chapter_id = $xpc->findvalue('@id', $chapter); 

    print "Chapter_Id=$chapter_id\n"; 
    print "Book_Publisher=$publisher\n"; 
    print "Book_Platform=$platform\n"; 
    print "\n"; 
    } 
} 

Оба стиля дают одинаковый результат:

Chapter_Id=bk444444ch1 
Book_Publisher=BKC 
Book_Platform=Science 

Chapter_Id=bk444444ch2 
Book_Publisher=BKC 
Book_Platform=Science 

Chapter_Id=bk444444ch1 
Book_Publisher=BKC 
Book_Platform=Science 

Chapter_Id=bk444444ch2 
Book_Publisher=BKC 
Book_Platform=Science 
+0

Спасибо Бородина! – Robie

+0

Это также можно сделать
мои% chapter_columns = ( Book_Publisher => '', ../../book:meta/@publisherId Book_Platform =>»../../book:meta/@platform ', ); – Robie

+0

@ ravi06: '..' - это то же самое, что и' parent: * ', и я считаю, что лучше использовать' ancestor' и указать * имя * элемента, чем использовать 'parent' дважды; во-первых, потому, что он самодокументирован (вам не нужно проверять XML, чтобы увидеть, какой элемент является родителем родителя элемента 'chapter', а во-вторых, потому что, если структура XML изменяется, это, вероятно, будет либо по-прежнему находите правильный элемент или он выдает ошибку, потому что такой узел не существует. Ваш путь будет просто выбирать этот элемент независимо от его имени. – Borodin

Смежные вопросы