在单个标记中找到n个相同的内部标记内容

时间:2021-02-22 12:13:43

how to get the inner tag content values of same tag which presented inside a single tag without newline character

如何获得在没有换行字符的单个标记中出现的相同标记的内部标记内容值

<BOOK-REF ID="Kyle-ch001-bib036"><AUTHOR-REF><SURNAME>Neinstein</SURNAME>, <GIVEN-NAME>L. S.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Gordon</SURNAME>, <GIVEN-NAME>C. G.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Katzman</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Rosen</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, &#x0026; <AUTHOR-REF><SURNAME>Woods</SURNAME>, <GIVEN-NAME>E.</GIVEN-NAME></AUTHOR-REF> (<YEAR-REF>2007</YEAR-REF>). <BOOK-TITLE-REF>Adolescent health care: A practical guide</BOOK-TITLE-REF> (<EDITION-REF>5th ed.</EDITION-REF>). <PLACE-OF-PUBLICATION-REF>Philadelphia</PLACE-OF-PUBLICATION-REF>: <PUBLISHER-REF>Lippincott Williams and Wilkins</PUBLISHER-REF>.</BOOK-REF>

I just want to get the content(name alone) inside thenametag and which presented inside the book ref tag,the surname tag may present n times and i want the content in an array

我只是想在thenametag中获取内容(名称),而在book ref标签中显示的内容,姓标签可能会显示n次,我希望内容在数组中

my (@arr2);
while ($str =~ /<BOOK-REF ID="([^"]*)">(?:[^\)]*)<SURNAME>(.*?)<\/SURNAME>.*?<YEAR-REF>(\d+\w+)<\/YEAR-REF>.*?<\/BOOK-REF>/sgi){
    my $id = $1;
    my $sname = $2;
    my $year = $3;
    push (@arr2,[$id,$sname,$year]);
}

thanks in advance

谢谢提前

3 个解决方案

#1


2  

With XML::Twig. I added a wrapper books around the book ref, in case you have more than one in the file. The code works just the same without it.

使用XML::树枝。我在book ref周围添加了一个包装书,以防文件中有多个。没有它,代码的工作原理是一样的。

#!/usr/bin/perl

use strict;
use warnings;

use YAML;
use XML::Twig;

my @by_name;
XML::Twig->new( twig_handlers => { 'BOOK-REF' => sub { book_ref( @_, \@by_name); } })
         -> parse( \*DATA);

print Dump \@by_name;

sub book_ref
  { my( $t, $bookref, $by_name)= @_;
    foreach my $surname ($bookref->descendants( 'SURNAME'))
      { push @$by_name, { name => $surname->text, id => $bookref->att( 'ID'), year =>  $bookref->field( 'YEAR-REF') }; }
    $t->purge; # if the file can be too big to fit in memory
  }



__DATA__
<books>
<BOOK-REF ID="Kyle-ch001-bib036"><AUTHOR-REF><SURNAME>Neinstein</SURNAME>, <GIVEN-NAME>L. S.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Gordon</SURNAME>, <GIVEN-NAME>C. G.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Katzman</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Rosen</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, &#x0026; <AUTHOR-REF><SURNAME>Woods</SURNAME>, <GIVEN-NAME>E.</GIVEN-NAME></AUTHOR-REF> (<YEAR-REF>2007</YEAR-REF>). <BOOK-TITLE-REF>Adolescent health care: A practical guide</BOOK-TITLE-REF> (<EDITION-REF>5th ed.</EDITION-REF>). <PLACE-OF-PUBLICATION-REF>Philadelphia</PLACE-OF-PUBLICATION-REF>: <PUBLISHER-REF>Lippincott Williams and Wilkins</PUBLISHER-REF>.</BOOK-REF>
</books>

#2


1  

Using XML::XSH2:

使用XML::XSH2:

#!/usr/bin/perl

use warnings;
use strict;

use Data::Dumper;

use XML::XSH2;
xsh << '    end xsh;';
    open 1.xml ;
    for //SURNAME {
        $y = string(../../YEAR-REF) ;
        $s = string(.) ;
        $i = string(ancestor::BOOK-REF/@ID) ;
        perl { push @arr, [$i, $s, $y] } }
    end xsh;
print Dumper \@XML::XSH2::Map::arr;

#3


0  

Use XPath queries to extract the values you are interested in. These three XPath queries should return the values you are looking for:

使用XPath查询提取感兴趣的值。这三个XPath查询应该返回您要查找的值:

//BOOK-REF/@ID
//BOOK-REF/AUTHOR-REF/SURNAME
//BOOK-REF/YEAR-REF

To do the XPath queries, use something like XML::LibXML. Complete example:

要执行XPath查询,请使用XML: LibXML。完整的例子:

#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;

my $xml = XML::LibXML->load_xml(string => q{<?xml version="1.0" encoding="utf-8"?>
<BOOK-REF ID="Kyle-ch001-bib036"><AUTHOR-REF><SURNAME>Neinstein</SURNAME>, <GIVEN-NAME>L. S.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Gordon</SURNAME>, <GIVEN-NAME>C. G.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Katzman</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Rosen</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, &#x0026; <AUTHOR-REF><SURNAME>Woods</SURNAME>, <GIVEN-NAME>E.</GIVEN-NAME></AUTHOR-REF> (<YEAR-REF>2007</YEAR-REF>). <BOOK-TITLE-REF>Adolescent health care: A practical guide</BOOK-TITLE-REF> (<EDITION-REF>5th ed.</EDITION-REF>). <PLACE-OF-PUBLICATION-REF>Philadelphia</PLACE-OF-PUBLICATION-REF>: <PUBLISHER-REF>Lippincott Williams and Wilkins</PUBLISHER-REF>.</BOOK-REF>
});

my $xc = XML::LibXML::XPathContext->new($xml);

my $id = $xc->find('//BOOK-REF/@ID');
my @snames = map $_->textContent => $xc->findnodes('//BOOK-REF/AUTHOR-REF/SURNAME');
my $year = $xc->find('//BOOK-REF/YEAR-REF');

print "$id\n";
print join(', ' => @snames), "\n";
print "$year\n";

# prints:
# Kyle-ch001-bib036
# Neinstein, Gordon, Katzman, Rosen, Woods
# 2007

You could save the results nicely in an array like this:

你可以把结果保存在这样的数组中:

push @some_array, +{
    id     => $id,
    snames => \@snames,
    year   => $year
};

If you want to follow your original scheme and duplicate the id and year for every sname, then it's:

如果你想遵循你的原始计划,并为每一个sname复制id和年份,那么它是:

push @arr2, map [ $id, $_, $year ] => @snames;

Another potentially useful way to store them would be in a hash keyed over the id field, so

存储它们的另一种可能有用的方法是在id字段上键入散列

$some_hash{$id} = +{
    id     => $id,
    snames => \@snames,
    year   => $year
};

#1


2  

With XML::Twig. I added a wrapper books around the book ref, in case you have more than one in the file. The code works just the same without it.

使用XML::树枝。我在book ref周围添加了一个包装书,以防文件中有多个。没有它,代码的工作原理是一样的。

#!/usr/bin/perl

use strict;
use warnings;

use YAML;
use XML::Twig;

my @by_name;
XML::Twig->new( twig_handlers => { 'BOOK-REF' => sub { book_ref( @_, \@by_name); } })
         -> parse( \*DATA);

print Dump \@by_name;

sub book_ref
  { my( $t, $bookref, $by_name)= @_;
    foreach my $surname ($bookref->descendants( 'SURNAME'))
      { push @$by_name, { name => $surname->text, id => $bookref->att( 'ID'), year =>  $bookref->field( 'YEAR-REF') }; }
    $t->purge; # if the file can be too big to fit in memory
  }



__DATA__
<books>
<BOOK-REF ID="Kyle-ch001-bib036"><AUTHOR-REF><SURNAME>Neinstein</SURNAME>, <GIVEN-NAME>L. S.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Gordon</SURNAME>, <GIVEN-NAME>C. G.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Katzman</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Rosen</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, &#x0026; <AUTHOR-REF><SURNAME>Woods</SURNAME>, <GIVEN-NAME>E.</GIVEN-NAME></AUTHOR-REF> (<YEAR-REF>2007</YEAR-REF>). <BOOK-TITLE-REF>Adolescent health care: A practical guide</BOOK-TITLE-REF> (<EDITION-REF>5th ed.</EDITION-REF>). <PLACE-OF-PUBLICATION-REF>Philadelphia</PLACE-OF-PUBLICATION-REF>: <PUBLISHER-REF>Lippincott Williams and Wilkins</PUBLISHER-REF>.</BOOK-REF>
</books>

#2


1  

Using XML::XSH2:

使用XML::XSH2:

#!/usr/bin/perl

use warnings;
use strict;

use Data::Dumper;

use XML::XSH2;
xsh << '    end xsh;';
    open 1.xml ;
    for //SURNAME {
        $y = string(../../YEAR-REF) ;
        $s = string(.) ;
        $i = string(ancestor::BOOK-REF/@ID) ;
        perl { push @arr, [$i, $s, $y] } }
    end xsh;
print Dumper \@XML::XSH2::Map::arr;

#3


0  

Use XPath queries to extract the values you are interested in. These three XPath queries should return the values you are looking for:

使用XPath查询提取感兴趣的值。这三个XPath查询应该返回您要查找的值:

//BOOK-REF/@ID
//BOOK-REF/AUTHOR-REF/SURNAME
//BOOK-REF/YEAR-REF

To do the XPath queries, use something like XML::LibXML. Complete example:

要执行XPath查询,请使用XML: LibXML。完整的例子:

#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;

my $xml = XML::LibXML->load_xml(string => q{<?xml version="1.0" encoding="utf-8"?>
<BOOK-REF ID="Kyle-ch001-bib036"><AUTHOR-REF><SURNAME>Neinstein</SURNAME>, <GIVEN-NAME>L. S.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Gordon</SURNAME>, <GIVEN-NAME>C. G.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Katzman</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, <AUTHOR-REF><SURNAME>Rosen</SURNAME>, <GIVEN-NAME>D.</GIVEN-NAME></AUTHOR-REF>, &#x0026; <AUTHOR-REF><SURNAME>Woods</SURNAME>, <GIVEN-NAME>E.</GIVEN-NAME></AUTHOR-REF> (<YEAR-REF>2007</YEAR-REF>). <BOOK-TITLE-REF>Adolescent health care: A practical guide</BOOK-TITLE-REF> (<EDITION-REF>5th ed.</EDITION-REF>). <PLACE-OF-PUBLICATION-REF>Philadelphia</PLACE-OF-PUBLICATION-REF>: <PUBLISHER-REF>Lippincott Williams and Wilkins</PUBLISHER-REF>.</BOOK-REF>
});

my $xc = XML::LibXML::XPathContext->new($xml);

my $id = $xc->find('//BOOK-REF/@ID');
my @snames = map $_->textContent => $xc->findnodes('//BOOK-REF/AUTHOR-REF/SURNAME');
my $year = $xc->find('//BOOK-REF/YEAR-REF');

print "$id\n";
print join(', ' => @snames), "\n";
print "$year\n";

# prints:
# Kyle-ch001-bib036
# Neinstein, Gordon, Katzman, Rosen, Woods
# 2007

You could save the results nicely in an array like this:

你可以把结果保存在这样的数组中:

push @some_array, +{
    id     => $id,
    snames => \@snames,
    year   => $year
};

If you want to follow your original scheme and duplicate the id and year for every sname, then it's:

如果你想遵循你的原始计划,并为每一个sname复制id和年份,那么它是:

push @arr2, map [ $id, $_, $year ] => @snames;

Another potentially useful way to store them would be in a hash keyed over the id field, so

存储它们的另一种可能有用的方法是在id字段上键入散列

$some_hash{$id} = +{
    id     => $id,
    snames => \@snames,
    year   => $year
};