perl@1983 has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I am looking to modify few XML values based on xpath and print the modified XML. Is there an easy way or existing module to do this? e.g. <XML> <TestElement>Hello</TestElement> </XML> to be convereted to <XML> <TestElement>Bye</TestElement> </XML>

Replies are listed 'Best First'.
Re: Modify XML
by toolic (Bishop) on Apr 04, 2011 at 17:02 UTC
    XML::Twig
    use warnings; use strict; use XML::Twig; my $xmlstr = '<XML> <TestElement>Hello</TestElement> </XML>'; my $twig = XML::Twig->new(twig_handlers => {'XML/TestElement' => sub { +$_->set_text('Bye')} }); $twig->parse($xmlstr); $twig->print(); __END__ <XML> <TestElement>Bye</TestElement> </XML>
      Hi toolic, Thanks for the solution. Will try this as well.
Re: Modify XML
by wind (Priest) on Apr 04, 2011 at 16:51 UTC
    Try XML::XPath
    use XML::XPath; use strict; use warnings; my $xml = do {local $/; <DATA>}; my $xp = XML::XPath->new( xml => $xml ); $xp->setNodeText('/XML/TestElement', 'Bye'); print $xp->findnodes_as_string('/'); __DATA__ <XML> <TestElement>Hello</TestElement> </XML>
      Thanks. This is what I was looking for. What does the below line mean actually? print $xp->findnodes_as_string('/');
Re: Modify XML
by locked_user sundialsvc4 (Abbot) on Apr 04, 2011 at 17:27 UTC

    Although there is an industry-standard method known as “XSLT” which can transform XML from one format to another (using another XML file to describe the transformations), I will very freely admit that I find it to be rather baffling every time I try to go that route.   (That is to say, every time I have to service legacy-code that went that route.)   Of course Perl supports XSLT.   However, I just like to use good ol’ XML::Twig and a little Perl code.   Twig is the “Swiss Army® Knife” for working with XML documents, and it can deal effectively with docs of any size at all.

    Twig supports a subset of XPath (an industry-standard way of locating things within an XML structure), and I have found that this subset is usually plenty enough to get the job done.   For example, it is what you would use (as has already been demonstrated in another reply) to locate the areas, within the XML, that you want to change.

Re: Modify XML
by richb (Scribe) on Apr 05, 2011 at 14:27 UTC
    Here's how I would do it with XML::LibXML. The query searches for the TestElement with "Hello" and changes it to "Bye".
    use strict; use warnings; use XML::LibXML; my $parser = XML::LibXML->new({"encoding" => "utf-8"}); my $doc = $parser->load_xml(string => "<XML> <TestElement>Hello</TestE +lement><TestElement>Some Other Element</TestElement></XML>"); my $qry = "/XML[TestElement='Hello']/TestElement/text()"; my ($node) = $doc->findnodes($qry); if (defined $node) { $node->setData("Bye"); } else { die "no match for $qry"; } print $doc->toString(), "\n";
    Output:
    <?xml version="1.0"?> <XML> <TestElement>Bye</TestElement><TestElement>Some Other Element</T +estElement></XML>
    Note that "Some Other Element" remains unchanged.
Re: Modify XML
by choroba (Cardinal) on Apr 05, 2011 at 22:20 UTC
    Using XML::XSH2:
    open 8997357.xml ; set /XML/TestElement[.='Hello'] "Bye" ; ls :d-1 ;