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

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.

Replies are listed 'Best First'.
Re^4: LibXML setNodeName error
by geddie2001 (Novice) on Jun 26, 2017 at 17:47 UTC
    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?
Re^4: LibXML setNodeName error
by geddie2001 (Novice) on Jun 26, 2017 at 20:07 UTC
    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.

        You are correct when I'm referring to an example like:
        <xsl:element name = "{foo}bar">
        In this instance, I would like that node to be left alone, unchanged. test input:
        <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" versi +on="1.0"> <xsl:element name="foo"> <xsl:element name="{bar}"/> </xsl:element> </xsl:stylesheet>
        test output:
        <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" versi +on="1.0"> <foo> <xsl:element name="{bar}"/> </xsl:element> </foo> </xsl:stylesheet>
        I'm sorry for changing the requirements.
Re^4: LibXML setNodeName error (updated)
by Anonymous Monk on Jun 27, 2017 at 15:56 UTC
    Create a new node, in the default namespace, and completely replace the existing element with it.