Input_0_Text Output_1_Text Input_0_Text Output_1_Text #### use strict; use warnings; use XML::Twig; my $XML=' '; # build a new file in the output format. my $Output_file_name='testOutput.xml'; my $outRoot=XML::Twig::Elt->new('Motors'); #process input XML data my $twig_roots={'Sheet'=>1}; my $twig_handlers={'Sheet' => \&Motors}; my $twig=new XML::Twig(TwigRoots=>$twig_roots, TwigHandlers=>$twig_handlers); $twig->parse($XML); #output results $outRoot->set_pretty_print('indented'); $outRoot->print_to_file($Output_file_name); sub Motors{ my ($twig, $Motor)=@_; my $motor_name=""; my $motorID=-1; # I want to find the ID of the Motor Instruction # This seems like what I want to do # $motorID = $Motor->first_child('Instruction')=>{Type=>'Motor'}->att('Name'); # Error: "Can't call method "att" on unblessed reference..." # This works but seems to be non-twigish foreach my $instr ($Motor->children('Instruction')){ #iterate through all the instructions on this sheet if($instr->att('Type') eq 'Motor'){ #this instruction is a motor type; set attributes $motorID=$instr->att('ID'); $motor_name=$instr->att('Name'); $outRoot->insert_new_elt('Motor'=>{Name=>$motor_name, ID=>$motorID}); } } # I want to find all wires that have a ToID or FromID that matches the motorID foreach my $wire ($Motor->children('Wire')){ #iterate through all wires on this sheet # do once for ToID if($wire->att('ToID') == $motorID){ #this is a wire that goes to the motor my $ToParam = $wire->att('ToText'); my $FromID = $wire->att('FromID'); my $FromText; #nested foreach -> lots of iteration :( foreach my $motor_item ($Motor->children()){ #iterate though all items on the sheet if (defined ($motor_item->att('ID'))){ #if the item has an ID attribute if($motor_item->att('ID')==$FromID){ #that matches the wire to the motor $FromText=$motor_item->att('Text'); #set output attribute } } } my $newRoot = $outRoot->first_child('Motor'=>{Name=>$motor_name}); #set current motor as root $newRoot->insert_new_elt('last_child', $ToParam, $FromText); #add this wire to output. } # do again for FromID pretty much the same as above. if($wire->att('FromID') == $motorID){ my $FromParam = $wire->att('FromText'); my $ToID = $wire->att('ToID'); my $ToText; foreach my $motor_item ($Motor->children()){ if (defined ($motor_item->att('ID'))){ if($motor_item->att('ID')==$ToID){ $ToText=$motor_item->att('Text'); } } } my $newRoot = $outRoot->first_child('Motor'=>{Name=>$motor_name}); $newRoot->insert_new_elt('last_child', $FromParam, $ToText); } } }