Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Using Perl to create XML

by Speedfreak (Sexton)
on Jul 20, 2000 at 20:14 UTC ( [id://23415]=perlquestion: print w/replies, xml ) Need Help??

Speedfreak has asked for the wisdom of the Perl Monks concerning the following question:

Hej All,

I've scoured here, CPAN and the web looking at XML::DOM, XML::Grove and XML::Parser but cant seem to figure this out.

I want to be able to compile and XML string from Perl using an object and then dump it out to a file. By using an object and simply giving it nodes, param and values it will reduce errors in the XML and make it easier to expand.

Example XML:
<house> <groundfloor> <room name="kitchen"> <item name="cooker" colour="white"> <item name="sink" colour="silver"> </room> <room name="lounge"> <item name="sofa" colour="turgid brown"> <item name="chair" colour="lime green"> </room> </groundfloor> </house>
Now, I'd like to be able to do something in Perl (pseudo code) like:
my $xmlDocument = XML::COOL:MODULE->new(document); $xmlDocument->{root} = "house"; $xmlDocument->addNode ("house", "groundfloor"); $xmlDocument->addElement ("item", "cooker", "white"); ... ... $xmlDocument->end; $xmlDocument->write ("myhouse.xml");
Get my drift?

Can anyone give me basic examples or source to get me started?

- Jed

formatting added by holli

Replies are listed 'Best First'.
Re: Using Perl to create XML
by btrott (Parson) on Jul 20, 2000 at 20:24 UTC
    The interface isn't quite like what you're asking about, but have you checked out XML::Writer?

    Example from the docs:

    use XML::Writer; use IO; my $output = new IO::File(">output.xml"); my $writer = new XML::Writer(OUTPUT => $output); $writer->startTag("greeting", "class" => "simple"); $writer->characters("Hello, world!"); $writer->endTag("greeting"); $writer->end(); $output->close();
Re: Using Perl to create XML
by lhoward (Vicar) on Jul 20, 2000 at 20:28 UTC
    This isn't quite what you are looking for either, but...

    One interesting approach would be to have a Data::Dumper like functionality that would output in XML format. Does anyone know if there is a moule out there that does this?

    $f{foo}=[{a=>5,b=>7},{a=>1,b=>2}]; print DumperXML(\%f);
    would print something like
    <foo> <element> <a>5</a> <b>7</b> </element> <element> <a>1</a> <b>2</b> </element> </foo>
    or something like that....
      Have you seen Data::DumpXML? It's *kind of* what you're talking about, but the resultant XML isn't quite like what you wrote.

      XML::Simple is another option. Its XMLout function takes a hash ref as an argument and dumps it in XML.

(raflach sample module) Re: Using Perl to create XML
by raflach (Pilgrim) on Jul 21, 2000 at 02:26 UTC

    I'm not familliar with the XML specification, but if you gave a true set of sample data, this quick hack would be able to produce that.

    First the script:
    #!/usr/local/bin/perl -w #Script use strict; use OOXML; my $xmldoc = new OOXML("house"); my $groundfloor = $xmldoc->node("groundfloor"); my $kitchen = $groundfloor->node("room", name=>"kitchen"); my $lounge = $groundfloor->node("room", name=>"lounge"); $kitchen->tag("item",name=>"cooker", colour=>"white"); $lounge->tag("item",name=>"sofa",colour=>"turgid brown"); $kitchen->tag("item",name=>"sink",colour=>"silver"); $lounge->tag("item",name=>"chair",colour=>"lime green"); print "First example... Matches yours\n"; $xmldoc->write(); my $secfloor = $xmldoc->node("2ndfloor", level => 2); my $bedroom = $secfloor->node("room", name=>"Bedroom 1", size=>"400 sq + ft"); my $bathroom = $secfloor->node("room", name=>"Bathroom", size=>"1/2"); $bedroom->tag("furniture",name=>"bed",colour=>"mahogony"); $bedroom->tag("furniture",name=>"dresser", colour=>"black"); $bedroom->tag("fixture", name=>"ceiling fan", colour=>"gold", action=> +"rotation"); $bathroom->tag("item", name=>"washcloth",colour=>"blue"); $bathroom->tag("furniture",name=>"sink", colour=>"white"); $bathroom->tag("furniture",name=>"toilet", colour=>"white"); my $saying = $bathroom->text(nodename=>"walldecor", name=>"saying"); $saying->text(text =>"If at first you don't fricasee; fry, fry a hen." +); $saying->text(nodename=>"strong",text=>"!!!!"); $saying->text(text =>"After the strong tag"); print "\n\n\nSecond example... more functionality\n"; $xmldoc->write(); print "\n\n\nThird example... set the increase(10) and starting(5) ind +ent levels\n"; $xmldoc->write(10,5); print "\n\n\nFourth example... Going to a file \"out.xml\"\n"; $xmldoc->write('','',"out.xml");




    And then the module

    #!/usr/local/bin/perl -w # Module package OOXML; use strict; sub new { my ( $class, $root, %params ) = @_; my $self={}; $self->{name} = $root; $self->{nodes} = (); $self->{tags} = (); $self->{params} = {}; if ( defined %params ) { for my $param ( keys %params ) { $self->{params}{$param} = $params{$param}; } } $self->{params}{type} = "main" if ( ! exists $self->{params}{type} + ); return bless $self, $class; } sub node { my ( $self, $node, %params ) = @_; push @{$self->{nodes}}, $self->new($node,type =>"node",%params); return bless $self->{nodes}[-1]; } sub tag { my ( $self, $tag, %params ) = @_; push @{$self->{tags}}, $self->new($tag,type=>"tag",%params); return bless $self->{tags}[-1]; } sub text { my ( $self, %params ) = @_; push @{$self->{nodes}}, $self->new("textnode",type=>"text",%params +); return bless $self->{nodes}[-1]; } sub write { my ( $self, $levelup, $level,$doc,$class ) = @_; my $node; $level = 0 if ( ! defined $level ) || $level eq ""; $levelup = 4 if ( ! defined $levelup ) || $levelup eq ""; if ( defined $doc ) { open STDOUT, ">>$doc" || return (1,"Couldn't open output file: $!" +); } print "\n" if ( $self->{params}{type} ne "text" && defined $class +&& $class->{params}{type} eq "text" ) ; print " " x $level if ($self->{params}{type} !~ /^text$/); print " " x $level if ($self->{params}{type} eq "text" && $class-> +{name} ne "textnode"); if ( $self->{params}{type} eq "text" ) { if ( exists $self->{params}{nodename} ) { print "<$self->{params}{nodename}"; for my $param ( keys %{$self->{params}} ) { next if ( $param eq "type" || $param eq "nodename" || $param e +q "text" ); print " $param=\"$self->{params}{$param}\""; } print ">"; } print "$self->{params}{text}" if ( exists $self->{params}{text} ); }else { print "<$self->{name}"; for my $param ( keys %{$self->{params}} ) { next if $param eq "type"; print " $param=\"$self->{params}{$param}\""; } print ">\n"; } my $test = 0; my $lastnode; for $node ( @{$self->{nodes}} ) { bless $node; print "\n" if $node->{name} ne "textnode" and ($test == 12); $test = $node->write($levelup, $level+$levelup, $doc, $self); $lastnode = bless $node; } for my $tag ( @{$self->{tags}} ) { bless $tag; if ( defined $lastnode && $lastnode->{name} eq "textnode" ) { print "\n"; undef $lastnode; } print " " x ( $level + $levelup) . "<$tag->{name}"; for my $param ( keys %{$tag->{params}} ) { next if $param eq "type"; print " $param=\"$tag->{params}{$param}\""; } print ">\n"; } if ( $self->{params}{type} eq "text") { if ( exists $self->{params}{nodename} ) { print "</$self->{params}{nodename}>"; } return 12; } else { print "\n" if ( defined $node && $node->{name} eq "textnode"); print " " x $level . "</$self->{name}>\n"; } return 0; } 1;

    Course it would be stupid to use this when there are peer reviewed/tried and true modules out there, that probably also adhere to the standard ( which this doesn't... lets you do pretty much whatever you want )... but it only took m a few minutes to throw together, so...

      Hi raflach, I tried to use your perl but adding the OOXML module through a "require" comand inside the calling perl. It fails for : "Attempt to bless into a reference at /...OOXML.pl line 21", which is the "return bless $self, $class" line. I tried without success with the lines :
      bless $self, $class; return $self
      What is the problem ? Thanks Jean-michel, Nemours, FRANCE
        What is the problem ?

        Allow me to introduce you to splain, a command-line interface to perldiag.

        C:\>splain C:\Perl\bin/splain.bat: Reading from STDIN Attempt to bless into a reference Attempt to bless into a reference (#1) (F) The CLASSNAME argument to the bless() operator is expected to +be the name of the package to bless the resulting object into. You've supplied instead a reference to something: perhaps you wrote bless $self, $proto; when you intended bless $self, ref($proto) || $proto; If you actually want to bless into the stringified version of the reference supplied, you need to stringify it yourself, for example by: bless $self, "$proto";

        So it turns out there is actually a bug in the OOXML.pm file.
        In subs new, tag, and text, he calls $self->new(...) which is precisely the trigger for the diagnostic above.
        Probably the easiest way to fix this is just to change return bless $self, $class; into return bless $self;
        That's not robust if OOXML is going to be subclassed, however. In that case, I'd recommend the following simple change instead:

        In sub new, immediately after the my( $class, ... line, insert the following line:

        $class = ref($class) if ref($class);

        I reckon we are the only monastery ever to have a dungeon stuffed with 16,000 zombies.
Re: Using Perl to create XML
by reptile (Monk) on Jul 20, 2000 at 21:40 UTC

    Answer: subclass XML::Parser. Take a look at XML::RSS for a good exmaple of subclassing XML::Parser. OO is your friend. Sorry I can't give an example here as it would be quite involved.

    local $_ = "0A72656B636148206C72655020726568746F6E41207473754A"; while(s/..$//) { print chr(hex($&)) }

Re: Using Perl to create XML
by arwa (Initiate) on Jul 21, 2000 at 04:54 UTC
    why don't use XML::Dumper?
      Hi Arwa, Sure, it would be better for me to use this kind of tool. But it is not installed on my PC ( Ubuntu 10.10 ). Being a beginner, I wonder if I can download it on the web and install it directly in my PERL modules directories or do I need to use CPAN ? Thanks Jean-michel

        Debian provides it as a package, so I bet Ubuntu does too.

        apt-get install libxml-dumper-perl

        PS — The name of the language is Perl (renamed from "Pearl"), not PERL.

Re: Using Perl to create XML
by cwest (Friar) on Jul 20, 2000 at 20:37 UTC
    Update:
    Geez, I hit the wrong button, I didn't want to post, but since I did, I might as well add my $0.02

    I think, if you wanted to, you could roll your own, if you already have some data structure in place.

    Otherwise, XML::Writer seems like a great solution for what you're asking.

    Unfortunatley, I don't have much else to say on the subject...

    my $mouse = 'a betrayer';
    --
    Casey
    

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-04-26 06:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found