in reply to Re: LibXML setNodeName error
in thread LibXML setNodeName error

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.

Replies are listed 'Best First'.
Re^3: LibXML setNodeName error (updated)
by haukex (Archbishop) on Jun 26, 2017 at 17:10 UTC

    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.

      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?
      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.

        So you have something like <xsl:element name="foo{bar">? That's not going to be valid as an XML element Name (<foo{bar>?), so what do you want the element to be named instead in that case?

        It's not an issue with XML::LibXML, which probably follows the XML spec precisely, but with XML itself. Also, as always, SSCCE - give us the shortest possible code that demonstrates the problem so we can see it.

      Create a new node, in the default namespace, and completely replace the existing element with it.