-1

My XML file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:element name="foo">
<xsl:value-of select="bar"/>
</xsl:element>
</xsl:stylesheet>

I'm using XML:LibXML::Reader and trying to perform logic on each node when certain criteria are meet. For example:

<xsl:element name="foo">

output:

<xsl:element name="foobar">

Here is what I currently have:

use strict;
use warnings;
use XML::LibXML::Reader;

my $reader = XML::LibXML::Reader->new(location => "test.xml") or die "cannot read input file\n";

while ($reader->read){
    processNode($reader);
}

sub processNode{
    my $reader = shift;
    printf "%s\n", ($reader->name);
}

My output looks like this:

xsl:stylesheet
#text
xsl:element
#text
xsl:value-of
#text
xsl:element
#text
xsl:stylesheet
Eddie Greathouse
  • 125
  • 1
  • 5
  • 14
  • This smells like an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Why do you need to walk a tree of nodes, and print them in exactly the same way? I mean, normally I'd just to `XML::LibXML` and use toString – Sobrique Jun 13 '17 at 16:56
  • I didn't make clear my full requirement because I was hoping it was a small tweak in my current script. I'm sorry for the confusion. This method would be great if I could do some manipulation to each line. For example, let's say I want to change every line that says: to: I hope this resolves any confusion. – Eddie Greathouse Jun 13 '17 at 17:42
  • OK. I've edited my answer - the question is easier to solve than you might think, thanks to `xpath`. – Sobrique Jun 14 '17 at 08:16

1 Answers1

1

Ok, the problem here is - you're essentially misunderstanding the tree nature of XML. You've got a bunch of nodes - that 'you're "walking"' but actually the xsl:stylesheet node is a parent of the xsl:element node.

By far the easiest way is to not do it the way you are, and instead:

#!/usr/bin/env perl

use strict;
use warnings;
use XML::LibXML;

my $reader = XML::LibXML->load_xml(location => "test.xml") or die "cannot read input file\n";
print $reader -> toString

But I'm pretty sure your requirement is something slightly more complicated.

Edit: And sure enough, it was.

So - change every 'foo' name to a 'foobar' name:

 #!/usr/bin/env perl

use strict;
use warnings;
use XML::LibXML;

my $reader = XML::LibXML->load_xml(location => "test.xml") or die "cannot read input file\n";
my $xpath_context = XML::LibXML::XPathContext->new($reader);

foreach my $foo_node ( $xpath_context -> findnodes('//xsl:element[@name="foo"]') ) {
  $foo_node -> setAttribute ( 'name', 'foobar' );
}

print $reader -> toString
Sobrique
  • 52,974
  • 7
  • 60
  • 101