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);
}