2013-07-21 73 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」;但沒有得到任何價值。

我不想改變在foreach循環中定義的xpath,但是意圖向後遍歷。 我如何實現這一目標?

我得到的結果是:

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

//@publisherId XPath表達式查找所有publisherId屬性文件。 (.//@publisherId發現當前節點下的所有這樣的屬性,但是這是不是你想要的,無論是。)

您需要使用ancestor軸找到包含此chapterbook元素,然後訪問從屬性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/@publisherIdmeta/@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:*'相同,我相信最好使用'祖先'並指定元素的*名稱*,而不是使用'parent'兩次;首先是因爲它是自我記錄(您不必檢查XML來查看「chapter」元素的父級的父級元素,其次是因爲如果XML的結構發生變化,則可能是仍然找到正確的元素,否則它會拋出一個錯誤,因爲這樣的節點不存在。你的方式只會選擇該元素,而不管它的名字。 – Borodin