Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re^5: Perl XML

by Tanktalus (Canon)
on Aug 10, 2005 at 02:15 UTC ( [id://482492]=note: print w/replies, xml ) Need Help??


in reply to Re^4: Perl XML
in thread Perl XML

I'm not going to write the code for you, but I did have a similar requirement that a particular element could exist prior to me trying to insert it. So I wrote a quick "xml_child" routine that would look for a specific element, return it if it were there, but if it weren't, it would create it, then return that. You can also provide parms for setting some stuff if the element is being created, or other parms for setting stuff whether it's being created or updated.

=item xml_child As a shortcut - given an XML element, find the child with the given na +me, or, if there isn't one, create it. This is the swiss-army-knife of XML functions for this pro +ject. If you do not understand this function after reading all the code, try + again or ask questions - this function is called for 90% of the work done to this XML file. Input: named parameters: =over 4 =item parent The parent object to look in. =item child The child name to look for/create =item action If the child needs to be created, this is the action to paste, see L<X +ML::Twig>. Default is 'last_child'. =item relto If the child needs to be created, this is where the action is relative + to. =item def_text If the child needs to be created, this is its default text, default to + blank. =item def_attr If the child needs to be created, this is its default attributes =item override_attr Whether or not the child existed prior, override its attributes with t +hese =item override_text Whether or not the child existed prior, override its text with this. =back There is no option for sub elements as that would just get way too con +fusing. Output: XML::Twig::Elt =cut sub xml_child { my %opts = @_; croak "parent option to xml_child must be XML::Twig::Elt" unless $opts{parent} and ref $opts{parent} and $opts{parent}-> +isa('XML::Twig::Elt'); my $child_name = $opts{child}; #$child_name = "$child_name" unless $child_name =~ m.^/.; my @children = $opts{parent}->children($child_name); croak "$child_name matches too many descendants" unless scalar @children < 2; # If no such child, create it. my $child; if (@children) { $child = $children[0]; } else { # here we need to create and paste a new element. my $action = $opts{action} || 'last_child'; my $rel = $opts{relto} || $opts{parent}; $child_name =~ s#(?:.*/)?(\w+).*#$1#; my @params = $child_name; push @params, $opts{def_attr} if exists $opts{def_attr}; push @params, $opts{def_text} if exists $opts{def_text}; $child = XML::Twig::Elt->new(@params); #eval { $child->paste($action, $rel); #}; if ($@) #{ # print STDERR "pasting $action ", $rel->gi(), " (name = ", + $rel->att('name'), ") failed\n"; # die $@; #} } $child->set_text($opts{override_text}) if exists $opts{override_te +xt}; $child->set_att(%{$opts{override_attr}}) if exists $opts{override_ +attr}; $child; }
Note that this was my first time using XML of any type, let alone XML::Twig, so be gentle with any criticisms ;-)

Example usage:

$child = xml_child(parent => $elt, child => 'built', action => 'after' +, relto => $prev_child, def_text => '19700101 000000.000-0000'); $prev_child = $child; $child = xml_child(parent => $elt, child => 'sha +reable', action => 'after', relto => $prev_child, override_text => 't +rue');
Here I'm creating a series of elements, and even specifying order by the order I insert (although if it's already there out of order, then I won't correct the order). I also have some default text which won't change anything that is already present but I have some override text that says that I don't care what the XML owner says, I'm changing the shareable element to be "true".

This is probably adaptable to what you sound like you need.

If you're wondering why the lack of whitespace in the example - it's because I have about 30 of these... and I just needed to get it done - after it was done, it was more important to be able to pgup/pgdn through past these constants than to make it readable. ;-> If I were doing it again, I'd find a way to put this data somewhere else and loop through it.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (5)
As of 2024-04-19 09:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found