Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
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 ( [id://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', } }

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 (Canon) 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
Domain Nodelet?
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?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2024-03-28 13:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found