This is close. The output is:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" versi
+on="1.0">
<xsl:foo>
<xsl:value-of select="bar"/>
</xsl:foo>
</xsl:stylesheet>
but what I was asking for was:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" versi
+on="1.0">
<foo>
<xsl:value-of select="bar"/>
</foo>
</xsl:stylesheet>
Everything you have done so far is great, thank you. If you can help me with this last piece, it will be perfect. I'm sorry for my ignorance. I have a lot to learn when it comes to Perl. | [reply] [d/l] [select] |
I remember doing battle with XML::LibXML in a similar situation a few years ago. IIRC, what I found back then is that the problem is namespaces - note how the document originally has only one namespace (http://www.w3.org/1999/XSL/Transform) with only one namespace prefix (xsl). What you're asking to do is move the node into a completely different namespace, specifically in this case the default one. I remember not being able to find the appropriate combinations of API calls to achieve this so that the resulting XML looked clean, and playing around by adding $element->setNamespace(...); to choroba's code seems to confirm this, the best I can do so far is <foo xmlns="...">. It seemed that once a node has been created in a namespace, it's stuck there you can't get it back into the default namespace cleanly. Back then I ended up writing a routine to create a new node in the new namespace. Now since this was a while ago, it's possible I missed the appropriate API function, but even now going through the XML::LibXML docs and Googling a bit I still don't see an obvious way.
<update2> Caveat: The below will completely ignore any other attributes in the element being replaced, so for example if you've got <xsl:element namespace=... or use-attribute-sets, that will be ignored and lost! </update2>
Here's what my workaround would look like (based in part on choroba's code):
use warnings;
use strict;
use XML::LibXML;
my $xml = <<'END_XML';
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Tr
+ansform">
<xsl:element name="foo">
<xsl:value-of select="bar"/>
</xsl:element>
</xsl:stylesheet>
END_XML
my $doc = XML::LibXML->load_xml(string => $xml) or die;
my $xpc = XML::LibXML::XPathContext->new($doc);
for my $el ($xpc->findnodes('//xsl:element')) {
my $newel = $doc->createElement($el->getAttribute('name'));
$newel->appendChild($_) for $el->childNodes;
$el->replaceNode($newel);
}
print $doc;
__END__
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" versi
+on="1.0">
<foo>
<xsl:value-of select="bar"/>
</foo>
</xsl:stylesheet>
Update: Made description more accurate. | [reply] [d/l] [select] |
Thank you wise Perl Monks! This is terrific. I was starting to write numerous sub routines and it just looked rubbish. I appreciate all your help. Is there anything I need to do to mark this question as answered?
| [reply] |
I've noticed a new issue. If the value of the name attribute contains the character "{" then I receive the error:
bad name at replaceelementname.pl line 8.
There may be other characters that causes this error as well. Any help would be appreciated. If I have to drop XML::LibXML completely, that is okay. | [reply] [d/l] |
Create a new node, in the default namespace, and completely replace the existing element with it.
| [reply] |