Perl 如何遍历到前面的父节点并获取XPath中元素的值?

Perl 如何遍历到前面的父节点并获取XPath中元素的值?,perl,xpath-2.0,Perl,Xpath 2.0,我试图在XPath中获取前一个节点的值,但要么得到重复的值,要么没有值 代码如下: use XML::LibXML; my %chapter_columns = ( 'Chapter_Id' => '@id', 'Chapter_Title' => 'book:locator[contains(@xlink:href, "format=epub")]/@xlink:title', 'Chapter_Doi_Prefix' => 'subs

我试图在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和//@platform获取“publisherId”和“platform”的价值。它们为每本书产生重复的价值。我甚至试着去拿它们“../../@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>

类似于
/@publisherId
的XPath表达式将查找文档根下的所有
publisherId
属性。(
//@publisherId
在当前节点下查找所有此类属性,但这也不是您想要的。)

您需要使用
祖先
轴查找包含该
章节
书籍
元素,然后从作为该书籍子元素的
元素访问属性。这段代码运行良好

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

也可以这样做
我的%chapter\u columns=(Book\u Publisher=>'../../Book:meta/@publisherId',Book\u Platform=>'../../Book:meta/@Platform',)@ravi06:
父项相同:
,我认为使用
祖先
并指定元素名称比使用
父项
两次更好;首先,因为它是自我记录的(您不必检查XML来查看哪个元素是
chapter
元素父元素的父元素,第二个原因是,如果XML的结构发生变化,它可能仍然会找到正确的元素,或者会抛出错误,因为这样的节点不存在。您的方法将简单地选择该元素,而不考虑其属性。)名称