views:

237

answers:

3

I have an XML file in a string variable ($data), and a hash containing all the tag names and their contents (%field_list).

The tag names are to be checked so that if they are enumerated fields, their contents should be replaced with strings.

Does anybody know if it is possible to do this with search and replace? I am not having much luck at the moment.

foreach my $field (sort keys %field_list)
{ 
    my $value = $field_list{$field};
    # will return a non-empty string if field is enumerated and value is valid
    my $enum_string = &convert_enumeration_to_string($field, $value);
    if ($enum_string ne "")
    {
#syntax error
$data =~ s/<($field)>($value)</($field)>/<($field)>($enum_string)</($field)>/g;
    }
} 

Does anybody know whether there is anything I can do, or do I need a completely different approach?

+3  A: 

Escape your slashes:

$data =~ s/<($field)>($value)<\/($field)>/<($field)>($enum_string)<\/($field)>/g;

Or use different deliminators:

$data =~ s{<($field)>($value)</($field)>}{<($field)>($enum_string)</($field)>}g;
Jack M.
I recommend not using `|` as a delimiter because then you can't use `|`-alternation in your pattern. My delimiter of choice is `s{}{}` which usually doesn't interfere with anything.
friedo
Hadn't really thought of that. I'll swap it out, thanks.
Jack M.
Thank you very much. So search and replace by variable is possible - the only thing I missed out is forgetting to insert backslashes in front of the forward slashes. Also, the brackets are not needed as it will mess up the output.
Andy
I'm at a loss as to why the brackets would change the output, but you're welcome.
Jack M.
You can even use `{}` in a `s{}{}` , as long as the`{}` are "nested". `s{{\w}}{}`
Brad Gilbert
Don't think the OP wants to have parenthesis in the replacement, thought.
Leonardo Herrera
A: 

The correct way to do it is:

$data =~ s/<($field)>($value)<\/($field)>/<$field>$enum_string<\/$field>/g;
Andy
Why was this downvoted? for being succint?
Leonardo Herrera
Just guessing, but parsing XML with regexes is almost NEVER the correct way to do it.
daotoad
No need to downvote an answer just because the question was bad. This does answer the question. The other answer got upvoted, and the first part of it is identical to this (except with that parentheses mistake/typo in the replacement).
Jefromi
+1  A: 

Well, let's jump into the XML bandwagon: use an XML library like XML::LibXML to manipulate XML documents.

use XML::LibXML;
my $dom = XML::LibXML->load_xml(string => $data);

foreach my $field (sort keys %field_list) {
    my $value = $field_list{$field};
    if (my $enum_string = &convert_enumeration_to_string($field, $value)) {
        foreach my $node ($dom->findnodes("//xml/${field}[. = '$value']")
            ->get_nodelist) {
            my $element = $dom->createElement($field);
            $element->appendText($enum_string);
            $node->replaceNode($element);
        }
    }
}

print $dom->toString;
Leonardo Herrera