Technical Discussion
  >> Linux Issues


Register (or login) on our website and you will not see this ad.


  Print Thread
Standard User think26872
(committed) Thu 05-May-11 15:38:43
Print Post

Any Perl XML Guru's?


[link to this post]
 
Can someone point me in the right direction in reading, manipulating and saving the following XML statement in Perl.

I want to work out how to find the contents of each the <fieldtwo> elements and then writing more elements <fieldthree> depending on what I find in <fieldtwo> for each item.

I have found information on reading OR writing but nothing that combines them both. There also seems to be many different XML libraries what is the standard one most people use?

Thanks

<items>
<item>
<fieldone>Morbi porttitor</fieldone>
<fieldtwo>Mauris sed mauris eu mauris auctor placerat.</fieldtwo>
</item>
<item>
<fieldone>Quisque vel</fieldone>
<fieldtwo>Fusce lacinia rhoncus ipsum, eget rutrum ipsum ullamcorper sed.</fieldtwo>
</item>
</items>
Standard User john2007
(legend) Thu 05-May-11 16:22:46
Print Post

Re: Any Perl XML Guru's?


[re: think26872] [link to this post]
 
Haven't used perl for over a decade. Why not C and glib?
Standard User think26872
(committed) Fri 06-May-11 07:56:59
Print Post

Re: Any Perl XML Guru's?


[re: john2007] [link to this post]
 
Should have made clear it is for a Linux script. I have also dabbled in Perl so for me at least I have a idea. Ill just do more Google search I am sure the answer is out there.


Register (or login) on our website and you will not see this ad.

Standard User AEP
(knowledge is power) Fri 06-May-11 08:42:44
Print Post

Re: Any Perl XML Guru's?


[re: think26872] [link to this post]
 
There's an example in this thread (7th post) that seems to be what you are looking for.
Standard User 12eason
(eat-sleep-adslguide) Fri 06-May-11 09:47:58
Print Post

Re: Any Perl XML Guru's?


[re: think26872] [link to this post]
 
The different types are the various dom traversal parsers, which is useless for big xml files but find stuff faster for small ones, and sax parsers, which are linear and event based and good for large files. The most basic ones are XML::Simple and XML::Writer, but they are pretty limited. You will probably have XML::Parser preinstalled which is a step up. I looked into this a while back because aaisp's free webhosting is perl only and I wanted to use some cgi to write to xml instead of a database for a jquery site. There are a few perl only scripts, like myxml and xml::sax::pureperl, but they aren't much good. Most of the decent ones rely on c parsers like expat to do the parsing. Personally I preferred xml::parser::perlsax because the event handlers were rather neat to code.

http://www.xml.com/pub/a/2000/04/05/feature/
http://perl-xml.sourceforge.net/perl-sax/sax-2.1-ref...

basic;
http://search.cpan.org/~josephw/XML-Writer-0.612/Wri...
http://search.cpan.org/~grantm/XML-Simple-2.18/lib/X...
http://search.cpan.org/~chorny/XML-Parser-2.40/Parse...

sax;
Pureperl sax parser: http://search.cpan.org/~grantm/XML-SAX-0.96/SAX.pm
expat based perlsax: http://search.cpan.org/~kmacleod/libxml-perl-0.08/li...

Don't know about the dom ones as I never used them. I'd imagined they'd be like xpath in browsers though.
Standard User 12eason
(eat-sleep-adslguide) Fri 06-May-11 22:16:58
Print Post

Re: Any Perl XML Guru's?


[re: think26872] [link to this post]
 
Not sure if this is any use to you, some old code I wrote that shows roughly how sax parsing works. It's just enough iirc to read and write to a file on a server from a client (which in my case was a jQueryUI interface thingy with user addable tabs), but there were some little bugs in it. I think you can get the jist of how it works from the comments I made as I stumbled my way through perl (evil). I remember now that sax chains were pretty sweet.

Perl
1
23
45
67
89
1011
1213
1415
1617
1819
2021
2223
2425
2627
2829
3031
3233
3435
3637
3839
4041
4243
4445
4647
4849
5051
5253
5455
5657
5859
6061
6263
6465
6667
6869
7071
7273
7475
7677
7879
8081
8283
8485
8687
8889
9091
9293
9495
9697
9899
100101
102103
104105
106107
108109
110111
112113
114115
116117
118119
120121
122123
124125
126127
128129
130131
132133
134135
136137
138139
140141
142143
144145
146147
148149
150151
152153
154155
156157
158159
160161
162163
164165
166167
168169
170171
172173
174175
176177
178179
180181
182183
#!/usr/bin/perl -w
 # the tabs system should allow user to group languange by attributes
 use strict;
use XML::Parser::PerlSAX;use XML::Handler::YAWriter;
use IO::File;use CGI;
use Switch; 
 #cache the values sent via ajax for new tab
my $cgi = CGI->new;my $tabLang = $cgi->param('lang');
my $tabIndex = $cgi->param('index');my $tabColour = $cgi->param('colour');
my $tabGroup = $cgi->param('group');my $mode = $cgi->param('mode');
 #make a backup of the existing nav.xml file
rename '../xml/nav.xml', '../xml/nav.xml.bak' || die "Could not back up nav.xml file";my $file = '../xml/nav.xml.bak' || die "Please pass a file name to process\n";
 #create the SAX pipeline: perlSAX parser > AddTab filter > YAWriter
my $writer = XML::Handler::YAWriter->new(Output => IO::File->new( ">../xml/nav.xml" )); #creates a new writermy $filter;
switch ($mode){        case "addTab" {
                $filter = AddTab->new(Handler => $writer);  #creates a new instance of AddTAb with handler set to $writer ^        }
        case "removeTab" {}        case "editTab" {}
        case "addMenu" {}        case "removeMenu" {}
        case "renameMenu" {}        case "" {}
        case "" {}}
my $parser = XML::Parser::PerlSAX->new(Handler => $filter); #creates a new instance of perlsax parser with handler set to $filter ^ 
#kick offmy %parser_args = (Source => {SystemId => $file});
$parser->parse(%parser_args); 
print $cgi->header,                $cgi->start_html("Success"), #need to return something
                $cgi->end_html;                
# end main 
# filter to insert new tabpackage AddTab;
{use strict;
use base qw(XML::SAX::Base); #inherits from sax baseuse Data::Dumper;
my $count = 1;        sub new { #factory
          my $class = shift;          my %options = @_;
          return bless \%options, $class; #makes options an object of class        };
                sub start_document {  #need to stop the writer adding an xml declaration
                my ($self, $something) = @_;                $count++;
                if($count == 1){   #check to see if this is the first document start event                        $self->SUPER::start_document($something);; #pass along to next in chain
                };        };
                sub start_element {
                my ($self, $element) = @_;                my $name = $element->{Name};
                my %attrs = %{ $element->{Attributes} };        
                #add tab when at index or increase index if after.                if ($name eq 'tab') {
                        if ($attrs{'index'} > $tabIndex){                                #we are past index so add 1 to the remaining tab indexes
                                $attrs{'index'} = $attrs{'index'} + 1;                                $element->{Attributes} = \%attrs; #set attributes to equal a pointer to our new hash
                        }                         elsif (($attrs{'index'} == $tabIndex) && ($attrs{'lang'} ne $tabLang)){
                                $self->insertTab(); #we are at index so insert the tab                                $attrs{'index'} = $attrs{'index'} + 1;
                                $element->{Attributes} = \%attrs; #set attributes to equal a pointer to our new hash                        };
                };                $self->SUPER::start_element($element);; #pass along to next in chain
        };        
        sub insertTab {                my $self = shift;
                my $parser2 = XML::Parser::PerlSAX->new({Handler => $self});                $parser2->parse("<tab lang='$tabLang' group='$tabGroup' index='$tabIndex' colour='$tabColour'></tab>");
         };
};        
# filter to remove existing tabpackage RemoveTab;
{use strict;
use base qw(XML::SAX::Base); #inherits from sax baseuse Data::Dumper;
my $count = 1;        sub new { #factory
          my $class = shift;          my %options = @_;
          return bless \%options, $class; #makes options an object of class        };
                sub start_document {  #need to stop the writer adding an xml declaration
                my ($self, $something) = @_;                $count++;
                if($count == 1){   #check to see if this is the first document start event                        $self->SUPER::start_document($something);; #pass along to next in chain
                };        };
                sub start_element {
                my ($self, $element) = @_;                my $name = $element->{Name};
                my %attrs = %{ $element->{Attributes} };        
                #add tab when at index or increase index if after.                if ($name eq 'tab') {
                        if ($attrs{'index'} > $tabIndex) {#we are past index so add 1 to the remaining tab indexes                                $attrs{'index'} = $attrs{'index'} - 1;
                                $element->{Attributes} = \%attrs; #set attributes to equal a pointer to our new hash                        } 
                        elsif (($attrs{'index'} == $tabIndex) && ($attrs{'lang'} eq $tabLang)){ #both index and lang match the tab to remove)                                #need to not pass on the tab untill the end tag is reached
                                $attrs{'index'} = $attrs{'index'} + 1;                                $element->{Attributes} = \%attrs; #set attributes to equal a pointer to our new hash
                        };                };
                $self->SUPER::start_element($element);; #pass along to next in chain        };
                sub end_element {
                my ($self, $element) = @_;                my $name = $element->{Name};
                my $removeSwitch = 'off';                
                if (($name eq 'tab') && ($removeSwitch eq 'off')) {                        
                                        };        };
        };
 # filter to change any of the attributes of a language tab
package changeTabAttr;{
        use strict;        use base qw(XML::SAX::Base); #inherits from sax base
        use Data::Dumper;};
#filter to add a menu group#each menu group should apply to multiple language tabs
#the title for each for each shared tabs my need to be different, ie functions vs subroutinespackage addMenuGroup;
{        use strict;
        use base qw(XML::SAX::Base); #inherits from sax base        use Data::Dumper;       
};#filter to remove an existing menu group
package removeMenuGroup;{
        use strict;        use base qw(XML::SAX::Base); #inherits from sax base
        use Data::Dumper;       };
package renameMenuGroup;{
        use strict;        use base qw(XML::SAX::Base); #inherits from sax base
        use Data::Dumper;               };
  Print Thread

Jump to