Skip Menu |

This queue is for tickets about the XML-Twig CPAN distribution.

Report information
The Basics
Id: 15014
Status: resolved
Priority: 0/
Queue: XML-Twig

People
Owner: MIROD [...] cpan.org
Requestors: fstrauss [...] ap.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 3.17
Fixed in: 3.22



Subject: Wrong type created in set_text
Distribution: XML-Twig-3.17 Perl Version: v5.8.5 Environment: Solaris 8 I believe I've uncovered a problem with the set_text() method of the XML::Twig::XPath::Elt. In stepping through the method it appears to create a new XML::Twig::Elt object to hold the new text. This however causes a problem when using the findnodes() method of the XML::Twig::XPath object as illustrated here: unknown node type XML::Twig::Elt at /tools/perl/lib/site_perl/5.8.5/XML/Twig/XPath.pm line 106. at /tools/perl/lib/site_perl/5.8.5/XML/Twig/XPath.pm line 106 XML::Twig::XPath::Elt::node_cmp('XML::Twig::XPath::Elt=HASH(0xbddbc8)', 'XML::Twig::Elt=HASH(0xb78218)') called at /tools/perl/lib/site_perl/5.8.5/XML/Twig/XPath.pm line 17 XML::XPath::NodeSet::sort('XML::XPath::NodeSet=ARRAY(0xb691f8)') called at /tools/perl/lib/site_perl/5.8.5/XML/XPath/Step.pm line 154 XML::XPath::Step::evaluate('XML::XPath::Step=HASH(0xc152d0)', 'XML::XPath::NodeSet=ARRAY(0xbc0574)') called at /tools/perl/lib/site_perl/5.8.5/XML/XPath/LocationPath.pm line 55 XML::XPath::LocationPath::evaluate('XML::XPath::LocationPath=ARRAY(0xc12960)', 'XML::Twig::XPath=HASH(0x423be0)') called at /tools/perl/lib/site_perl/5.8.5/XML/XPath/Expr.pm line 138 XML::XPath::Expr::evaluate('XML::XPath::Expr=HASH(0xbfc6dc)', 'XML::Twig::XPath=HASH(0x423be0)') called at /tools/perl/lib/site_perl/5.8.5/XML/XPath.pm line 86 XML::XPath::find('XML::XPath=HASH(0x9dff00)', '//Paragraph[contains(., "(PROFILE")]', 'XML::Twig::XPath=HASH(0x423be0)') called at /tools/perl/lib/site_perl/5.8.5/XML/XPath.pm line 102 XML::XPath::findnodes('XML::XPath=HASH(0x9dff00)', '//Paragraph[contains(., "(PROFILE")]', 'XML::Twig::XPath=HASH(0x423be0)') called at /tools/perl/lib/site_perl/5.8.5/XML/Twig/XPath.pm line 49 XML::Twig::XPath::findnodes('XML::Twig::XPath=HASH(0x423be0)', '//Paragraph[contains(., "(PROFILE")]') called at tmp2.pl line 23 I believe the root issue here is that node_cmp method is looking for an XML::Twig::XPath::Elt and getting an XML::Twig::Elt object instead. I have attached a sample data file and here's the script. To run it use: perl tmp2.xml <datafile> =================================== use strict; use English; use XML::Twig::XPath; # find the start of the AP profile my $xpath_document = new XML::Twig::XPath; $xpath_document->parsefile($ARGV[0]); $xpath_document->set_pretty_print('nice'); # Now translate any 8-bit AP Internal chars to 7-bit ANPA in any text # in the document foreach my $current_node ($xpath_document->root->descendants) { if ($current_node->contains_only_text) { my $source_text = $current_node->text; if (translate_ap_internal_chars(\$source_text)) { $current_node->set_text($source_text); } } } # add the text from all subsequent paragraph nodes to our profile buffer my @source_profile_nodes = $xpath_document->findnodes("//Paragraph[contains(., \"(PROFILE\")]"); my $current_node = $source_profile_nodes[0]; my $profile_buf; while ($current_node) { $profile_buf .= $current_node->child_text(); $current_node = $current_node->next_sibling(); } # insert a new element with the profile buffer in it before the Paragraph # element we found the profile in my $ap_profile_node = XML::Twig::XPath::Elt->new("APProfile" => $profile_buf); $ap_profile_node->paste('before', $source_profile_nodes[0]); my $current_node = $source_profile_nodes[0]; while ($current_node) { my $next_node = $current_node->next_sibling(); $current_node->delete(); $current_node = $next_node; }
use strict; use English; use XML::Twig::XPath; # find the start of the AP profile my $xpath_document = new XML::Twig::XPath; $xpath_document->parsefile($ARGV[0]); $xpath_document->set_pretty_print('nice'); # Now translate any 8-bit AP Internal chars to 7-bit ANPA in any text # in the document foreach my $current_node ($xpath_document->root->descendants) { if ($current_node->contains_only_text) { my $source_text = $current_node->text; if (translate_ap_internal_chars(\$source_text)) { $current_node->set_text($source_text); } } } # add the text from all subsequent paragraph nodes to our profile buffer my @source_profile_nodes = $xpath_document->findnodes("//Paragraph[contains(., \"(PROFILE\")]"); my $current_node = $source_profile_nodes[0]; my $profile_buf; while ($current_node) { $profile_buf .= $current_node->child_text(); $current_node = $current_node->next_sibling(); } # insert a new element with the profile buffer in it before the Paragraph # element we found the profile in my $ap_profile_node = XML::Twig::XPath::Elt->new("APProfile" => $profile_buf); $ap_profile_node->paste('before', $source_profile_nodes[0]); my $current_node = $source_profile_nodes[0]; while ($current_node) { my $next_node = $current_node->next_sibling(); $current_node->delete(); $current_node = $next_node; } $xpath_document->print(); sub translate_ap_internal_chars { # use a reference so we modify the actual text my $content_text_ref = shift; # INT_CFS my $replaced_text = (${$content_text_ref} =~ s/\\xb1/\\x1c/g); # INT_TLI $replaced_text |= (${$content_text_ref} =~ s/\\xb2/\\x08/g); # INT_TFI $replaced_text |= (${$content_text_ref} =~ s/\\xb3/\\x1f/g); # INT_EMLDR $replaced_text |= (${$content_text_ref} =~ s/\\xb4/*/g); # INT_ENLDR $replaced_text |= (${$content_text_ref} =~ s/\\xb5/#/g); # INT_EMSP $replaced_text |= (${$content_text_ref} =~ s/\\xb7/\\x19/g); # INT_ENSP $replaced_text |= (${$content_text_ref} =~ s/\\xb8/\\x1e/g); # INT_THIN $replaced_text |= (${$content_text_ref} =~ s/\\xb9/\\x1d/g); # INT_SPBND $replaced_text |= (${$content_text_ref} =~ s/\\xb0/\\x10/g); # INT_1_8 $replaced_text |= (${$content_text_ref} =~ s/\\xa6/[/g); # INT_1_4 $replaced_text |= (${$content_text_ref} =~ s/\\xbc/\\\\/g); # INT_3_8 $replaced_text |= (${$content_text_ref} =~ s/\\xa8/]/g); # INT_1_2 $replaced_text |= (${$content_text_ref} =~ s/\\xbd/{/g); # INT_5_8 $replaced_text |= (${$content_text_ref} =~ s/\\xa9/|/g); # INT_3_4 $replaced_text |= (${$content_text_ref} =~ s/\\xbe/}/g); # INT_7_8 $replaced_text |= (${$content_text_ref} =~ s/\\xac/!/g); # INT_PARA $replaced_text |= (${$content_text_ref} =~ s/\\xb6/\\t/g); # INT_QC $replaced_text |= (${$content_text_ref} =~ s/\\xa2/=/g); # INT_QR $replaced_text |= (${$content_text_ref} =~ s/\\xa3/>/g); # INT_QL $replaced_text |= (${$content_text_ref} =~ s/\\xa4/</g); # INT_UR $replaced_text |= (${$content_text_ref} =~ s/\\xa5/^/g); # INT_LR $replaced_text |= (${$content_text_ref} =~ s/\\xae/@/g); return($replaced_text); }
Hi, It is quite late and Idon't have time to test your code, but a quick look at the module code shows that indeed, the new element should be created in the same class as the original, which is easily done by calling $elt->new instead of XML::Twig::Elt->new. I applied that change there, and in a few other methods. This still passes the tests, so it might do the trick. The updated version is on the (updated!) usual site: http://xmltwig.com/xmltwig/ Let me know if this fixes your problem and I'll do the paperwork (add test, update Changes...) tomorrow. Thanks, nice catch __ mirod
OK, the development version is fixed and tested (and I found and fixed an other bug in the process). And I received an other bug report for this bug today, which also got quite a short turn-around time. ;--) Thanks __ mirod