# # lolxml # # Rev. 0.1 Jan. 31, 2010 by zhuo # Rev. 0.2 Feb. 02, 2010 zhuo # # A module to generate an XML string (maybe long) from a list of # lists organized in a specific manner. # # Usage: # 1. Build a list of lists in a specific format (see the appendix # for the format details) : # # $lol = [ ..... ]; # # 2. Call the toxml function to generate a XML string. # # $xmlstring = lolxml::toxml( $lol, "", " " ); # # Here, the second argument, "" in this example, specifies the # default indentation prefix. This is inserted at the beginning of # every line in the output. # The third argument, " " in this example, specifies the extra # indentation string appended to the default indentation prefix # every time the nest level increases. # # # Appendix: list-of-list format detail # # COMMENT: # [ 'str' ] <-> # # TREE CONSTRUCTION RULES: # # single value: # [ 'key0', 'val0' ] <-> val0 # # nest: # [ 'key0', ['key1', 'val1'] ] <-> val1 # # listing: # [ 'key0', ['key1', 'val1'], ['key2','val2'],... ] <-> val1val2... # # ATTRIBUTES: # # 1) The attribute specifier for a single tag: # # 1-a) With a scalar value at the third element, a single value inside # a nest is treated as an attribute: # [ 'key0', ['key1', 'val1', ''] ] <-> # [ 'key0', ['key1', '', ''] ] <-> # # 1-b) An empty key results in a hidden attribute-name field. # [ 'key0', ['', 'val1', ''] ] <-> # # 1-c) An empty key with an empty value results in an empty single tag. # [ 'key0', ['', '', ''] ] <-> # Note that this list does not result in , as expected # from the example ; # # 2) The attribute specifier for an open-close tag pair: # To force a paired tag representation in stead of a single # tag, put a non-attribute element or more in the listing: # [ 'key0', ['key1', 'val1', ''], '' ] <-> # [ 'key0', ['key1', 'val1', ''], 'val0' ] <-> val0 # [ 'key0', ['key1', 'val1', ''], ['key2', 'val2'] ] <-> val2 package lolxml; use Exporter; @ISA = qw(Exporter); @EXPORT = qw( toxml ); sub toxml { my ( $pNode, $offset, $indent ) = @_; if ( @$pNode == 1 ) { return sprintf( "%s\n", $offset, $pNode->[0] ); } my ( $key, @args ) = @$pNode; my $attr = ''; my $body = ''; foreach my $e ( @args ) { if ( ref($e) ne 'ARRAY' ) { ## a single value return sprintf( "%s<%s%s>%s\n", $offset, $key, $attr, $e, $key ); } if ( @$e == 3 && ref($e->[1]) eq '' ) { ## an attribute $attr .= ' '; if ( $e->[0] ne '' ) { $attr .= sprintf( '%s=', $e->[0] ); } if ( $e->[0] ne '' || $e->[1] ne '' ) { $attr .= sprintf( '"%s"', $e->[1] ); } } else { ## internal structure $body .= toxml( $e, $offset . $indent, $indent ); } } if ( $body eq '' ) { return sprintf( "%s<%s%s/>\n", $offset, $key, $attr ); } return sprintf( "%s<%s%s>\n%s%s\n", $offset, $key, $attr, $body, $offset, $key ); } 1; __END__