Xml.pl
- !/usr/bin/perl
- A snipit for reading/writing nodal XML files
- - It can handle: Attributes, Mixed content
- - It cannot handle: Badly formed XML, CDATA sections
use strict;
- The XML is parse into a tree
- - each node in the tree is a hash of attributes plus .name and .content keys
- - each .content value is a ref to a list of ordered nodes/texts
- - only one root is allowed
sub xmlParse {
# First convert XML into a list split at every tag, ie. <tag> </tag> or <tag/> # - Each tag is five list items (first /, name, atts, second /, text between this and next) @_ = shift =~ /<\s*(\/?)([-a-z0-9_:]+)\s*(.*?)\s*(\/)?>\s*(.*?)\s*(?=<|$)/gi;
# Loop through all the tags and compile them into a tree my $ptr = my $root = {}; my @path = (); while ( $#_ >= 0 ) { my ( $close, $name, $atts, $leaf, $text ) = ( shift, shift, shift, shift, shift ); # Create a new node in the current content and update ptr if <tag/> or <tag> # - Includes hash of atts: /PATTERN/g returns a key,val list which can be treated as a hash unless ($close) { my $node = { '.name' => $name, $atts =~ /([-a-z0-9_:]+)\s*=\s*"(.*?)"/gi }; push @{$$ptr{'.content'}}, $node; # Push the node onto the current content list push @path, $ptr; # Move current focus into the new node $ptr = $node; } $ptr = pop @path if $close or $leaf; # Move ptr up one level is </tag> or <tag/> push @{$$ptr{'.content'}}, $text if $text; # Add the after-node-content part to the current level }
return $root; }
- Construct XML text from passed hash tree
sub xmlBuild { my ($level, $ptr) = @_; my $indent; $indent .= ' ' for 1..$level; my $name = $$ptr{'.name'}; print "$indent$name\n" if $name; for ( @{$$ptr{'.content'}} ) { xmlBuild( $level+1, $_ ) if ref eq 'HASH'; } }
- Test
xmlBuild 1, xmlParse ' <test>hello</test> <properties a="1" b="1" > content <test2 b="eee"/>xxx <properties a="1" b="1" > content <test2 b="eee"/>xxx </properties> </properties> <associations a="1" b="ddd"/> ';



