Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

[SOLVED] XML::Twig - '#CDATA' attribute in hashref disappears after first call to XML::Twig::Elt->new()

by ateague (Monk)
on Jul 20, 2018 at 21:56 UTC ( [id://1218967]=perlquestion: print w/replies, xml ) Need Help??

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

Update:
This behavior is correct as per the source code.
(Sure wish there was an explanatory blurb explaining that XML::Twig::Elt->new() removes the '#CDATA' key in an attribute hashref. C'est la vie.)

Thank you haukex and Anon Monk for your explanation and workarounds!


Good afternoon!

I am experiencing a rather unexpected issue creating new elements with XML::Twig's XML::Twig::Elt->new() method where the '#CDATA' key in my attribute hashref gets undefined after passing it to new().

e.g.:

my $attributes = $sibling_element->atts(); $attributes->{'#CDATA'} = 1; # '#CDATA' attribute is defined here my $elt1 = XML::Twig::Elt->new('present', $attributes, 'This is in CDA +TA'); # '#CDATA' attribute is undefined here my $elt2 = XML::Twig::Elt->new('missing', $attributes, 'This is not in + CDATA');

Is this supposed to happen? I did not see anything mentioning this in the CPAN docs...

Thank you for your time.

Perl info:

perl -v This is perl 5, version 26, subversion 0 (v5.26.0) built for MSWin32-x +64-multi-thread
XML::Twig info: 3.52

Sample code:
#!/usr/bin/perl use 5.026; use strict; use warnings; use XML::Twig; { open (my $OFILE, '>:utf8', 'file.out.xml') or die "$!\n$^E"; my $t = XML::Twig->new( twig_handlers => { '/keys/key' => sub { makeDuplicates(@_, $OFILE); 1; }, }, output_encoding => 'utf-8', pretty_print => 'indented', ); $t->safe_parse(\*DATA); if ( $@ ) { die "Error occured in XML data\n$@"; } close $OFILE; } sub makeDuplicates { my ($_twig, $key_element, $OFILE) = @_; my $text = $key_element->text(); my $attributes = $key_element->atts(); $attributes->{'#CDATA'} = 1; # '#CDATA' attribute is defined here my $lc_element = XML::Twig::Elt->new('lc_key', $attributes, lc $text +); # '#CDATA' attribute is undefined here my $uc_element = XML::Twig::Elt->new('uc_key', $attributes, uc $text +); $lc_element->paste(after => $key_element); $uc_element->paste(after => $key_element); $_twig->flush($OFILE); return; } __DATA__ <?xml version="1.0" encoding="utf-8"?> <keys> <key order='01'><![CDATA[One hen]]></key> <key order='02'><![CDATA[Two ducks]]></key> <key order='03'><![CDATA[Three squawking geese]]></key> <key order='04'><![CDATA[Four limerick oysters]]></key> <key order='05'><![CDATA[Five corpulent porpoises]]></key> <key order='06'><![CDATA[Six pair of Don Alverzo's tweezers]]></key> <key order='07'><![CDATA[Seven thousand Macedonians in full battle a +rray]]></key> <key order='08'><![CDATA[Eight brass monkeys from the ancient sacred + crypts of Egypt]]></key> <key order='09'><![CDATA[Nine apathetic, sympathetic, diabetic old m +en on roller skates, with a marked propensity towards procrastination + and sloth]]></key> <key order='10'><![CDATA[Ten lyrical, spherical, diabolical denizens + of the deep who stalk about the corners of the cove all at the same +time.]]></key> </keys>

Desired output:


Actual output:

  • Comment on [SOLVED] XML::Twig - '#CDATA' attribute in hashref disappears after first call to XML::Twig::Elt->new()
  • Select or Download Code

Replies are listed 'Best First'.
Re: XML::Twig - '#CDATA' attribute in hashref disappears after first call to XML::Twig::Elt->new()
by haukex (Archbishop) on Jul 21, 2018 at 12:51 UTC
    Is this supposed to happen?

    Well, it appears to be intentional, the code includes:

    $CDATA = '#CDATA'; ... package XML::Twig::Elt; ... sub new ... if( $atts && defined $atts->{$CDATA}) { delete $atts->{$CDATA}; my $cdata= $class->new( $CDATA => @_); return $class->new( $gi, $atts, $cdata); }

    So new assumes that it's ok to modify the hashref. Whether this is good design is debatable, but if you want to just work with the module as is, the workaround provided by the AM here creates a shallow copy of the hash, so that new is free to delete keys. Alternatively, you could do what the above code is doing, that is, wrap the data in a CDATA yourself.

Re: XML::Twig - '#CDATA' attribute in hashref disappears after first call to XML::Twig::Elt->new()
by Anonymous Monk on Jul 21, 2018 at 02:56 UTC

    Is this supposed to happen? I did not see anything mentioning this in the CPAN docs... spoilers

    Sure, why not? Its constructor, it does what it wants , with the stuff you give it , and with the stuff it gives you

    spoiler spoiler spoiler

    Yeah spoiler tags are for spoilers, not to hide your questions

      my $uc_element = XML::Twig::Elt->new('uc_key', {%$attributes}, uc $text);

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-04-25 21:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found