2012-05-31 5 views
3

Я новичок в XML :: Twig, и я пытаюсь разобрать финальный выпуск PubMed XML 2.0, чтобы разместить его в базе данных mySQL. Я получил это далеко:Parsing PubMed XML для отправки в базу данных mySQL (XML :: Twig)

#!/bin/perl -w 
use strict; 
use DBI; 
use XML::Twig; 

my $uid = ""; 
my $title = ""; 
my $sortpubdate = ""; 
my $sortfirstauthor = ""; 
my $dbh = DBI->connect ("DBI:mysql:medline:localhost:80", 
          "root", "mysql"); 
my $t= new XML::Twig( twig_roots => { 'DocumentSummary' => $uid => \&submit }, 
         twig_handlers => { 'DocumentSummary/Title' => $title, 'DocumentSummary/SortPubDate' => $sortpubdate, 'DocumentSummary/SortFirstAuthor' => $sortfirstauthor}); 
$t->parsefile('20112.xml'); 
$dbh->disconnect(); 
exit; 

sub submit 
    { my $insert= $dbh->prepare("INSERT INTO medline_citation (uid, title, sortpubdate, sortfirstauthor) VALUES (?, ?, ?, ?);"); 
     $insert->bind_param(1, $uid); 
     $insert->bind_param(2, $title); 
     $insert->bind_param(3, $sortpubdate); 
     $insert->bind_param(4, $sortfirstauthor); 
     $insert->execute(); 
     $t->purge; 
    } 

Но по какой-то причине Perl, похоже, заглох. Правильно ли я это делаю? Я пытаюсь использовать twig_roots для уменьшения количества парсинга, так как меня интересуют только несколько полей (это большие файлы).

Вот пример XML:

<DocumentSummary uid="22641317"> 
    <PubDate>2012 Jun 1</PubDate> 
    <EPubDate></EPubDate> 
    <Source>Clin J Oncol Nurs</Source> 
    <Authors> 
     <Author> 
      <Name>Park SH</Name> 
      <AuthType> 
       Author 
      </AuthType> 
      <ClusterID>0</ClusterID> 
     </Author> 
     <Author> 
      <Name>Knobf MT</Name> 
      <AuthType> 
       Author 
      </AuthType> 
      <ClusterID>0</ClusterID> 
     </Author> 
     <Author> 
      <Name>Sutton KM</Name> 
      <AuthType> 
       Author 
      </AuthType> 
      <ClusterID>0</ClusterID> 
     </Author> 
    </Authors> 
    <LastAuthor>Sutton KM</LastAuthor> 
    <Title>Etiology, assessment, and management of aromatase inhibitor-related musculoskeletal symptoms.</Title> 
    <SortTitle>etiology assessment and management of aromatase inhibitor related musculoskeletal symptoms </SortTitle> 
    <Volume>16</Volume> 
    <Issue>3</Issue> 
    <Pages>260-6</Pages> 
    <Lang> 
     <string>eng</string> 
    </Lang> 
    <NlmUniqueID>9705336</NlmUniqueID> 
    <ISSN>1092-1095</ISSN> 
    <ESSN>1538-067X</ESSN> 
    <PubType> 
     <flag>Journal Article</flag> 
    </PubType> 
    <RecordStatus> 
     PubMed - in process 
    </RecordStatus> 
    <PubStatus>4</PubStatus> 
    <ArticleIds> 
     <ArticleId> 
      <IdType>pii</IdType> 
      <IdTypeN>4</IdTypeN> 
      <Value>N1750TW804546361</Value> 
     </ArticleId> 
     <ArticleId> 
      <IdType>doi</IdType> 
      <IdTypeN>3</IdTypeN> 
      <Value>10.1188/12.CJON.260-266</Value> 
     </ArticleId> 
     <ArticleId> 
      <IdType>pubmed</IdType> 
      <IdTypeN>1</IdTypeN> 
      <Value>22641317</Value> 
     </ArticleId> 
     <ArticleId> 
      <IdType>rid</IdType> 
      <IdTypeN>8</IdTypeN> 
      <Value>22641317</Value> 
     </ArticleId> 
     <ArticleId> 
      <IdType>eid</IdType> 
      <IdTypeN>8</IdTypeN> 
      <Value>22641317</Value> 
     </ArticleId> 
    </ArticleIds> 
    <History> 
     <PubMedPubDate> 
      <PubStatus>entrez</PubStatus> 
      <Date>2012/05/30 06:00</Date> 
     </PubMedPubDate> 
     <PubMedPubDate> 
      <PubStatus>pubmed</PubStatus> 
      <Date>2012/05/30 06:00</Date> 
     </PubMedPubDate> 
     <PubMedPubDate> 
      <PubStatus>medline</PubStatus> 
      <Date>2012/05/30 06:00</Date> 
     </PubMedPubDate> 
    </History> 
    <References> 
    </References> 
    <Attributes> 
     <flag>Has Abstract</flag> 
    </Attributes> 
    <PmcRefCount>0</PmcRefCount> 
    <FullJournalName>Clinical journal of oncology nursing</FullJournalName> 
    <ELocationID></ELocationID> 
    <ViewCount>0</ViewCount> 
    <DocType>citation</DocType> 
    <SrcContribList> 
    </SrcContribList> 
    <BookTitle></BookTitle> 
    <Medium></Medium> 
    <Edition></Edition> 
    <PublisherLocation></PublisherLocation> 
    <PublisherName></PublisherName> 
    <SrcDate></SrcDate> 
    <ReportNumber></ReportNumber> 
    <AvailableFromURL></AvailableFromURL> 
    <LocationLabel></LocationLabel> 
    <DocContribList> 
    </DocContribList> 
    <DocDate></DocDate> 
    <BookName></BookName> 
    <Chapter></Chapter> 
    <SortPubDate>2012/06/01 00:00</SortPubDate> 
    <SortFirstAuthor>Park SH</SortFirstAuthor> 
</DocumentSummary> 

Спасибо!

ответ

0

Ваш синтаксис обработчиков неверен. Смотрите documentation для примера:

my $twig=XML::Twig->new( 
    twig_handlers => 
     { title => sub { $_->set_tag('h2') }, # change title tags to h2 
     para => sub { $_->set_tag('p') }, # change para to p 
     hidden => sub { $_->delete;  }, # remove hidden elements 
     list => \&my_list_process,   # process list elements 
     div  => sub { $_[0]->flush;  }, # output and free memory 
     }, 
    pretty_print => 'indented',    # output will be nicely formatted 
    empty_tags => 'html',     # outputs <empty_tag /> 
         ); 
+0

Тем не менее некоторые проблемы, даже после упрощения кода: 'моего $ ДВГА = DBI-> подключения ("DBI: MySQL: MEDLINE: LOCALHOST: 80", «root», «mysql»); my $ t = new XML :: Twig (twig_roots => {'Title' => \ & process, 'SortPubDate' => \ & process, 'SortFirstAuthor' => \ & process}); $ t-> parsefile ('20112.xml'); \t $ dbh-> disconnect(); выход; подпроцесс \t {\t my ($ t, $ elt) = @_; \t my $ column = $ elt-> text; \t \t my $ value = $ elt -> {'att'}; \t \t my $ insert = $ dbh-> prepare ("INSERT INTO medline_citation $ column VALUES $ value;"); \t \t $ insert-> execute(); \t \t $ t-> flush; \t} ' – user1428925

1

Как я хотел бы сделать это, чтобы иметь один обработчик, для DocumentSummary, который питает БД, а затем удаляет запись. Нет необходимости становиться более привлекательным, чем это.

Кроме того, я нахожу DBIx :: Simple, а, проще в использовании, чем сырой DBI, он заботится о подготовке и кэширования заявлений для меня:

#!/bin/perl 

use strict; 
use warnings; 

use DBIx::Simple; 
use XML::Twig; 

my $db = DBIx::Simple->connect ("dbi:SQLite:dbname=t.db"); # replace by your DSN 

my $t= XML::Twig->new( twig_roots => { DocumentSummary => \&submit },) 
       ->parsefile('20112.xml'); 

$db->disconnect(); 
exit; 

sub submit 
    { my($t, $summary)= @_; 
     my $insert= $db->query("INSERT INTO medline_citation (uid, title, sortpubdate, sortfirstauthor) VALUES (?, ?, ?, ?);", 
           $summary->att('uid'), 
           map { $summary->field($_) } (qw(Title SortPubDate SortFirstAuthor)) 
          ); 
     $t->purge; 
    } 

Если вам интересно о map { $summary->field($_) } (qw(Title SortPubDate SortFirstAuthor)), это просто любитель (и имхо более ремонтопригоден) способ написать $summary->field('Title'), $summary->field('SortPubDate'), $summary->field('SortFirstAuthor')