2010-11-28 6 views
1

Je travaille sur un script Perl qui doit remplir un fichier XML basé sur l'entrée de l'utilisateur. L'utilisateur fournirait un nom de pays et un nom de ville. Si il/elle fournit: japon et e, j'ai besoin de peupler cela dans la balise japan - mais comme la dernière entrée. Comment puis-je y arriver? Les villes en tag pays peuvent être nombreuses. Comment puis-je ajouter une ville comme dernière balise dans la balise country correspondante?Script Perl pour remplir un fichier XML

Comment puis-je atteindre à la fin de l'étiquette de pays pertinente chaque fois que j'ai besoin d'ajouter une ville? PS: Je n'utilise aucune structure de données intégrée pour stocker des données. J'ajoute juste des lignes muettes dans le fichier.

Samlple fichier XML de sortie:

<country name="japan-"> 
    <city>a</city> 
    <city>b</city> 
    <city>c</city> 
    <city>d</city> 
</country> 
<country name="china-"> 
    <city>aa</city> 
    <city>bb</city> 
    <city>cc</city> 
    <city>dd</city> 
</country> 

J'ai une question plus concrète, Change an XML file content via Perl script.

Répondre

4

XML::Simple est ... Simple. :) Il ne nécessite un élément racine si:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use XML::Simple; 
use Data::Dumper; 

my $xml = join "\n", <DATA>; 
my $doc = XMLin($xml, KeepRoot => 1); 

# Get the list of cities as a list, then push "Tokyo" to it. 
push @{$doc->{countries}->{country}->{'japan-'}->{city}}, 'Tokyo'; 

print XMLout($doc, KeepRoot => 1); 

__DATA__ 
<countries> 
    <country name="japan-"> 
     <city>a</city> 
     <city>b</city> 
     <city>c</city> 
     <city>d</city> 
    </country> 
    <country name="china-"> 
     <city>aa</city> 
     <city>bb</city> 
     <city>cc</city> 
     <city>dd</city> 
    </country> 
</countries> 

Sortie:

<countries> 
    <country name="china-"> 
    <city>aa</city> 
    <city>bb</city> 
    <city>cc</city> 
    <city>dd</city> 
    </country> 
    <country name="japan-"> 
    <city>a</city> 
    <city>b</city> 
    <city>c</city> 
    <city>d</city> 
    <city>Tokyo</city> 
    </country> 
</countries> 
+0

Great Mikael :) Comment puis-je analyser un fichier xml existant et y ajouter une entrée? – hari

+0

Merci Mikael, j'ai aussi besoin d'ajouter un nouveau pays lorsque l'utilisateur demande d'ajouter un pays qui n'y est pas déjà. – hari

+0

Salut Mikael, je ne suis pas en mesure d'atteindre le noeud exact, je suppose. Mon "push" ne fonctionne pas comme prévu. – hari

0

Je pense que vous vouliez dire: Comment charger un fichier XML et y ajouter des entrées en fonction de l'entrée de l'utilisateur? Si j'ai bien compris: Vous utilisez un analyseur/analyseur tel que XML :: Simple (il y en a apparemment de meilleurs comme XML :: Twig aussi, donc explorez un peu) pour charger le fichier dans une structure de données Perl de hachages et tableaux. (Utilisez Data :: Dumper pour vérifier à quoi il ressemble en mémoire.) Ensuite, vous modifiez cette structure avec l'interaction de données Perl normale et lorsque vous avez terminé, utilisez l'éditeur pour la reconvertir en XML.

+0

Désolé pour la confusion. Je sais écrire du contenu xml. Ma question est sur la façon d'ajouter une ville comme dernière entrée dans l'étiquette de pays. Ai-je besoin de parcourir toutes les entrées de la ville existante et quand j'atteins la dernière balise, j'ai besoin d'ajouter la ville nouvellement demandée. Comment y parvenir? – hari

+0

Euh, si vous lisez le fichier XML avec un analyseur, vous aurez un hachage de pays, triés par clé (dans le meilleur des cas), chacun contenant un tableau de villes pour chaque pays. Il vous suffit donc de sélectionner la bonne valeur dans le hash du pays, d'obtenir son tableau de villes et de pousser sur ce tableau. Où est la difficulté? – Mithaldu

+0

Merci Mithaldu, j'apprends encore à travailler avec XML en Perl. – hari

0

Voici une solution à l'aide XML::Twig. Je pense que ça fait ce que tu veux. Les caractéristiques les plus notables de XML :: Twig sont l'utilisation de l'option id => name pour traiter l'attribut name comme un ID, donc les éléments peuvent être trouvés directement avec $t->elt_id, et la méthode insert_new_elt pour créer un nouvel élément dans l'arborescence. Sa signature est (<position: before, after, first_child or last_child>, <tag_name>, <{attributes}>, <content>),

#!/usr/bin/perl 

use strict; 
use warnings; 

use XML::Twig; 

my $t= XML::Twig->new(id => 'name', # treat the name attribute as an ID 
         pretty_print => 'indented' 
        ) 
       ->parse(\*DATA); 

add_city($t, japan => "Kobe"); 
add_city($t, japan => "Tokyo"); 
add_city($t, china => "Beijing"); 
add_city($t, china => "Shanghai"); 
add_city($t, japan => "Kobe"); 
add_city($t, south_korea => "Seoul"); 

$t->print; 

sub add_city 
    { my($t, $country_name, $city_name)= @_; 

    my $country= $t->elt_id($country_name); 
    if(! $country) 
     { warn "creating country '$country_name'\n"; 
     $country= $t->root->insert_new_elt(last_child => country 
              => { name => $country_name } 
             ); 
     } 

    if($country->first_child(qq{city[text()="$city_name"]})) 
     { warn "city '$city_name' already found in '$country_name', skipping\n"; 
     return; 
     } 

    warn "adding '$city_name' to '$country_name', skipping\n"; 
    $country->insert_new_elt(last_child => 'city', $city_name); 
    } 


__DATA__ 
<countries> 
    <country name="japan"> 
    </country> 
    <country name="china"> 
    </country> 
</countries> 
+0

Merci Mirod pour la réponse. Dans mon cas, je dois apporter des modifications (ajout) à un fichier xml existant. Comment puis-je charger mon fichier xml existant? – hari

+0

Appréciez votre aide. J'ai posté une question plus concrète ici: http://stackoverflow.com/questions/4301435/change-an-xml-file-content-via-perl-script – hari

+0

le fichier xml est chargé lorsque la méthode d'analyse est appelée.Vous pouvez ensuite accéder aux éléments via la navigation, en utilisant first/last_child, children, parent ou prev/next_siblin, directement en utilisant elt_id ou en utilisant XPath avec findnodes, finvalue ... – mirod

Questions connexes