Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

How to use perl to parsing a XML file to csv file which have the same sequence in xml file?

by carol.j (Initiate)
on Jun 14, 2012 at 10:05 UTC ( #976168=perlquestion: print w/ replies, xml ) Need Help??
carol.j has asked for the wisdom of the Perl Monks concerning the following question:

How to use perl to parsing a XML file to csv file which have the same sequence in xml file? The following XML file called booklist.xml, in example:

<book> <author>Book 1 author 1</author> <author>Book 1 author 2</author> <title>Book 1 title</title> <isbn>Book1ISBN</isbn> </book>

Example of Converting from XML to a Perl hash record

#!/usr/bin/perl # Script to illustrate how to parse a simple XML file # and dump its contents in a Perl hash record. use strict; use XML::Simple; use Data::Dumper; my $booklist = XMLin('booklist.xml'); print Dumper($booklist);

Running this script outputs the following:

$VAR1 = { 'book' => { 'isbn' => 'Book1ISBN', 'title' => 'Book 1 title', 'author' => [ 'Book 1 author 1', 'Book 1 author 2' ] } }

But hope we can get the sequence like this:

$VAR1 = { 'book' => { 'author' => [ 'Book 1 author 1', 'Book 1 author 2' ] 'title' => 'Book 1 title', 'isbn' => 'Book1ISBN', } }

Comment on How to use perl to parsing a XML file to csv file which have the same sequence in xml file?
Select or Download Code
Replies are listed 'Best First'.
Re: How to use perl to parsing a XML file to csv file which have the same sequence in xml file?
by tobyink (Abbot) on Jun 14, 2012 at 12:01 UTC

    In you care about the order of those elements XML::Simple (or indeed any similar XML-to-hashref tool) is not your friend. Perl hashes do not preserve order. There are modules that give you order-preserving hashes (via ties) but persuading XML::Simple to use them is probably not possible.

    use PerlX::MethodCallWithBlock; use Text::CSV; use XML::LibXML 1.94; local $\ = "\n"; my $xml = XML::LibXML->load_xml(IO => \*DATA); my $csv = Text::CSV->new; foreach my $book ($xml->findnodes('/library/book')) { my $row = $book->findnodes('./*')->map{ $_->textContent }; $csv->print(\*STDOUT, $row); } __DATA__ <library> <book> <author>Book 1 author 1</author> <author>Book 1 author 2</author> <title>Book 1 title</title> <isbn>Book1ISBN</isbn> </book> <book> <author>Book 2 author 1</author> <author>Book 2 author 2</author> <title>Book 2 title</title> <isbn>Book2ISBN</isbn> </book> </library>

    The output from the above is:

    "Book 1 author 1","Book 1 author 2","Book 1 title",Book1ISBN
    "Book 2 author 1","Book 2 author 2","Book 2 title",Book2ISBN
    
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      Hello

      I tried to run the example provided here, and I get the following error:

       Expected fields to be an array ref at xml.pl line 11

      When I look at the contents of $book, I see:

      $VAR1 = bless( [ 'Book 1 author 1', 'Book 1 author 2', 'Book 1 title', 'Book1ISBN' ], 'XML::LibXML::NodeList' ); $VAR1 = bless( [ 'Book 2 author 1', 'Book 2 author 2', 'Book 2 title', 'Book2ISBN' ], 'XML::LibXML::NodeList' );
      I am running perl 5.10.1 -- any tips?

        It worked on my machine, but Text::CSV's behaviour can be a little variable - it has two underlying implementations: one in pure Perl, and a faster one in C. Which one you get is the luck of the draw. In this case, $row is a blessed arrayref; Text::CSV expects an arrayref; it looks like one of the implementations rejects the arrayref if it's blessed but the other does not.

        $csv->print(\*STDOUT, [@$row]); # unblessed shallow clone of $row
        perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

        I am running perl 5.10.1 -- any tips?

        Forget it, its magic :) I get

        PL_linestr not long enough, was Devel::Declare loaded soon enough in f +udge at PerlX/MethodCallWithBlock.pm line 107.

        Report it to PerlX::MethodCallWithBlock maintainer

Re: How to use perl to parsing a XML file to csv file which have the same sequence in xml file?
by Utilitarian (Vicar) on Jun 14, 2012 at 10:48 UTC
    Could you give us an example record of the csv file you wish to output?

    print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
Re: How to use perl to parsing a XML file to csv file which have the same sequence in xml file?
by Anonymous Monk on Jun 14, 2012 at 10:31 UTC

    Running this script outputs the following: ... But hope we can get the sequence like this: ...

    Those two are identical data structures

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://976168]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (15)
As of 2015-07-30 14:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (271 votes), past polls