2014-05-25 3 views
3
use XML::LibXML; 
use Data::Dumper; 

#parsing file 
my $dom = XML::LibXML->new->parse_file('sample.xml'); 

my $context = XML::LibXML::XPathContext->new($dom->documentElement() ); 
$context->registerNs('u', 'http://uniprot.org/uniprot'); 

#print file to make sure it looks ok 
print $dom, "\n"; 

    #finds shortnames 
    my $sn = $context->findnodes('//u:shortName'); 
    print 'ShortName: '.$sn, "\n"; 

    #finds dbRefernce ids that are of type EC 
    my $ids = $context->findnodes('//u:dbReference[@type="EC"]/@id'); 
    my $number =()= $ids =~ /\./gi; 
    print 'EC Values: '.$ids, "\n"; 

    #finds sequences that have a length 
    my $seq = $context->findnodes('//u:sequence[@length>1]'); 
    $seq =~ s/" "/"\n"/; 
    print 'Sequence: '.$seq, "\n"; 

J'ai actuellement ce code, qui fonctionne sur ce fichier xml qui a 10 balises (https://www.dropbox.com/s/dq8ir9f22cnfwrz/Sample.xml). Pour l'instant, il extrait le nom court, dbReference et la séquence des 10 entrées dans ce fichier xml et les ajoute ensemble pour imprimer. Ce que je voudrais faire, il a un nom court, dbReference, et une séquence pour chaque entrée dans le fichier xml. Est-il possible que le script recherche ces données une à la fois pour chaque entrée? Mon but final est de les formater d'une manière spécifique pour la sortie.extractibles et Stockage de données XML avec Libxml/XPath

Je pensais avoir du code qui s'exécute avant, qui n'extrait que les entrées, puis les envoie au reste du code pour l'extraction des données.

Merci

Répondre

2

Vous devez interroger un ensemble de nœuds (qui retourne une collection):

my @entries = $context->findnodes('//u:entry'); 

Ensuite, pour chaque noeud vous exécutez une expression XPath contextuelle findnodes(expression, context-node), en passant le noeud comme le deuxième argument, par exemple:

foreach $entry (@entries) { 
    my $entryName = $context->findnodes('u:name', $entry); 
    ... 
} 

Voici une tentative en utilisant votre code:

use XML::LibXML; 
use Data::Dumper; 

#parsing file 
my $dom = XML::LibXML->new->parse_file('sample.xml'); 

my $context = XML::LibXML::XPathContext->new($dom->documentElement() ); 
$context->registerNs('u', 'http://uniprot.org/uniprot'); 

my @entries = $context->findnodes('//u:entry'); 
foreach $entry (@entries) { 

    my $entryName = $context->findnodes('u:name', $entry); 
    my @shortNames = $context->findnodes('.//u:shortName', $entry); 
    my @dbRefs  = $context->findnodes('.//u:dbReference[@type="EC"]/@id', $entry); 
    my $sequence = $context->findnodes('.//u:sequence[@length>1]'); 

    print "============================================================\n"; 
    print "\nName: ".$entryName."\n"; 

    print "\nShort Names: \n"; 
    $i=0; 
    foreach $shortName (@shortNames) { 
     print ++$i.': '.$shortName->firstChild, "\n"; 
    } 

    print "\nEC Values: \n"; 
    $i=0; 
    foreach $dbRef (@dbRefs) { 
     print ++$i.': '.$dbRef->nodeValue, "\n"; 
    } 

    $sequence =~ s/" "/"\n"/; 
    print "\nSequence: ".$sequence, "\n"; 
} 
+0

Impressionnant. Merci l'homme – bforcer

+0

Juste une question rapide. Comment puis-je appeler la taille de la liste de nœuds. Il suffit de jouer avec le script – bforcer

+0

Dans XPath, vous pouvez utiliser la fonction 'count()': 'count (// u: entry)' retournera le nombre d'entrées (il y a beaucoup d'autres fonctions: jetez un oeil aux exemples XPath @Miller posté dans sa réponse). En utilisant DOM, vous pouvez utiliser la propriété 'length' (vous pouvez également rechercher une référence DOM - elle est presque indépendante de la langue). – helderdarocha

1

Il ressemble //sequence est votre intérêt principal, vous avez juste besoin de parcourir les valeurs renvoyées par findnodes:

for my $seq ($context->findnodes('//u:sequence[@length>1]')) { 
    print 'Sequence @length: '.$seq->getAttribute('length'). "\n"; 
    # ... 
} 

Ensuite, il vous suffit de tirer les autres valeurs relatives à ce noeud. Pour savoir comment faire, juste google XML::LibXML Namespace et le troisième résultat est un poste de PerlMonks: XML::LibXML and namespaces

for my $seq ($context->findnodes('//u:sequence[@length>1]')) { 
    print 'Sequence @length: '.$seq->getAttribute('length'). "\n"; 

    my @sn = $context->findnodes('..//u:shortName', $seq); 
    print ' ShortName Count: '[email protected] "\n"; 

    my @ids = $context->findnodes('..//u:dbReference[@type="EC"]/@id', $seq); 
    print ' EC Values Count: '[email protected] "\n"; 
} 

sortie (Note, tous les suivants a un shortName):

Sequence @length: 323 
    ShortName Count: 5 
    EC Values Count: 7 
Sequence @length: 503 
    ShortName Count: 0 
    EC Values Count: 5 
Sequence @length: 323 
    ShortName Count: 3 
    EC Values Count: 4 
Sequence @length: 490 
    ShortName Count: 0 
    EC Values Count: 4 
Sequence @length: 490 
    ShortName Count: 0 
    EC Values Count: 4 
Sequence @length: 323 
    ShortName Count: 3 
    EC Values Count: 3 
Sequence @length: 323 
    ShortName Count: 3 
    EC Values Count: 3 
Sequence @length: 539 
    ShortName Count: 2 
    EC Values Count: 3 
Sequence @length: 494 
    ShortName Count: 1 
    EC Values Count: 3 
Sequence @length: 277 
    ShortName Count: 0 
    EC Values Count: 3 

Pour obtenir des conseils supplémentaires sur la façon de construire XPaths, consultez: XPath Examples

Questions connexes