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

I have written some perl that SHOULD search a xml file and change some elemnts, but it fails when I try to change the element. The code is below followed by the xml.
use TeamSite::WFtask; use TeamSite::WFworkflow; use LWP::UserAgent; use XML::DOM; $iwhome = getiwhome(); $iwmnt = getiwmount(); my $task = new TeamSite::WFtask($ARGV[1]); my $task_id = $ARGV[1]; my $workarea = $task->GetArea(); my @iw_files = $task->GetFiles(); my $iw_file; $modDir = $workarea; $modDir =~ s!/!\\!i; #loop over files foreach $iw_file (@iw_files) { $iw_file =~ m#templatedata\\([^\\]*)\\([^\\]*)\\data\\(.*)#; my $category = $1; my $type = $2; my $dcr = $3; my $dcr = "test.xml"; #$iw_file = "e:\\iw-home\\bin\\bespoke\\test.xml"; if ($dcr){ print " Category : $category \n"; print " Type : $type \n"; print " DCR : $dcr \n"; #if ($type eq "mainarticle"){ print " File : $iw_file \n"; $xml = change_dcr_attr("$iwmnt$modDir\\$iw_file","External + Link Heading","test","file",""); $xml =~ s/\r/ /g; $xml =~ s/\n/ /g; $xml =~ s/\t/ /g; $xml =~ s/ //g; print "$xml"; $xml = change_dcr_attr("$iwmnt$modDir\\$iw_file","Body Cop +y Heading","test","string",$xml); print "$xml"; #} } } sub change_dcr_attr { #print " And the games begin... \n"; my ($dcr,$element_name,$element_value,$type,$xml) = @_; my $parser=new XML::DOM::Parser; #parse the document print "type : $what \n"; if ($type eq "file"){ $dcr_doc=$parser->parsefile($dcr) || die "unable to parse docum +ent: $!"; } else { $dcr_doc=$parser->parsestring($xml) || die "unable to parse doc +ument: $!" } #get all tags my $dcr_items = $dcr_doc->getElementsByTagName('item'); # iterate over all tags for my $i (0..$dcr_items->getLength-1) { my $dcr_item=$dcr_items->item($i); # get the value of the ‘name’ attrribute my $dcr_item_name = $dcr_item->getAttribute("name"); #process only required field #e.g.’Surname’ next unless $dcr_item_name eq $element_name; # drill down to the tag my $dcr_item_child = $dcr_item->getFirstChild; # get down to the text we want to change my $dcr_text_node = $dcr_item_child->getFirstChild if defined $dc +r_item_child; if (defined ($dcr_text_node)) { if (( $dcr_text_node->getNodeType == TEXT_NODE) ) { # finally change the value $dcr_text_node->setData($element_value); } } else { if ($type eq "string"){ print "Error\n"; return 0; } } } return $dcr_doc->toString; #return the whole DCR XML as a string } sub getiwhome { my $iwhome = TeamSite::Config::iwgethome(); #only needed on solaris #$iwhome =~ s#\\#/#g; return $iwhome; } sub getiwmount { my $iwmount = TeamSite::Config::iwgetmount(); $iwmount =~ s#\\#/#g; return $iwmount; } <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <record name="ktest"> <item delimiter=", " name="______________________ PRIMARY CON +TENT"> </item> <item delimiter=", " name="File Location"> <value>tech</value> </item> <item delimiter=", " name="Body Copy Heading"> <value>fffffffffffffffffffffffffsdsdsd</value> </item> <item delimiter=", " name="Body Replicant"> <value> <item delimiter=", " name="Body Copy"> <value>test</value> </item> <item delimiter=", " name="______________________ I +MAGES"> </item> <item delimiter=", " name="Image"> <value></value> </item> <item delimiter=", " name="Caption Heading"> <value></value> </item> <item delimiter=", " name="Caption Copy"> <value></value> </item> </value> </item> </record>
Edited 2001-03-23 by Ovid

Replies are listed 'Best First'.
Re: parse xml
by mirod (Canon) on Mar 23, 2001 at 21:41 UTC

    As I can't test your code easilly I will venture 2 hypothesis: either you have a Perl problem, please use strict;, some of your variables are not declared, or you have a DOM-induced problem with \n and generally whitespaces creating text nodes when you are not expecting them, see my comment in the code.

    The following works for me, I just took your code, extracted the relevant function and got it to work:

    #!/bin/perl -w use strict; use XML::DOM; my $xml; $xml=change_dcr_attr (\*DATA, "change", "changed text", "string"); print $xml; sub change_dcr_attr { my ($dcr,$element_name,$element_value,$type) = @_; my $parser=new XML::DOM::Parser; my $dcr_doc; # COMMENT was not declared #parse the document print "type : $type \n"; # COMMENT you had $what here if ($type eq "file"){ $dcr_doc=$parser->parsefile($dcr) || die "unable to parse d +ocument: $!"; } else { $dcr_doc=$parser->parsestring($dcr) || die "unable to parse + document: $!" } #get all tags # COMMENT: unless you're into heavy B&D there is no need to write Ja +va # in Perl # my $dcr_items = $dcr_doc->getElementsByTagName('item'); # # iterate over all tags # # for my $i (0..$dcr_items->getLength-1) { # my $dcr_item=$dcr_items->item($i); # This is simpler foreach my $dcr_item ($dcr_doc->getElementsByTagName('item')) { # get the value of the name attrribute my $dcr_item_name = $dcr_item->getAttribute("name"); #process only required field #e.g.?Surname? next unless $dcr_item_name eq $element_name; # drill down to the tag my $dcr_item_child = $dcr_item->getFirstChild; # COMMENT: VERY + dangerous # if a \n or a +comment slips in # you should lo +op until you get # an element # COMMENT this saves you when you come across the last item below $dcr_item_child= $dcr_item_child->getNextSibling until( $dcr_item_child->getNodeType == ELEMENT_NODE); # get down to the text we want to change my $dcr_text_node = $dcr_item_child->getFirstChild if defined +$dcr_item_child; if (defined ($dcr_text_node)) { if (( $dcr_text_node->getNodeType == TEXT_NODE) ) { # finally change the value $dcr_text_node->setData($element_value); } } else { if ($type eq "string"){ print "Error\n"; return 0; } } } return $dcr_doc->toString; #return the whole DCR XML as a string } __DATA__ <doc> <item name="change"><sub>text to be changed</sub></item> <item name="change"><sub>text to be changed</sub></item> <item name="do not change"><sub>should remain unchanged</sub></item> <item name="change"> <sub>text to be changed</sub> </item> </doc>
Re: parse xml
by aardvark (Pilgrim) on Mar 23, 2001 at 19:44 UTC
    It would be helpful to see the error you are getting when you try to change the element. It's much harder to help you if we can't see exactly what's going wrong. Especially since you're running this under TeamSite and it doesn't seem like the TeamSite Modules are on the CPAN. Also are you using strict and warnings (-w)? If not, use them, learn to love the pain.

    Get Strong Together!!