0

I'm working with an older version of Python (2.3) for a legacy system, and I don't have ElementTree available (which was since 2.5...). The xml.dom package seems to be the best interface I have for parsing and editing XML documents, but if you find something infeasible or blatantly wrong here, please feel free to steer me in another direction.

I'm having trouble changing the XML I've parsed. I want to set all of my tags to have a particular prefix/namespace, so I wrote this function:

def recursive_set_ns(root):
    # type: (Element) -> None
    """Set namespaces for all tags recursively by DFS."""
    if (root.prefix is None) or (root.prefix == ""):
        root.prefix = "some_prefix"
    if not root.hasChildNodes():
        # Probably not necessary, though good to have for logic.
        return
    for child_tag in root.childNodes:
        recursive_set_ns(child_tag)

For some reason, the variable root.prefix does in fact get updated, but when I print it out with document.toxml or document.writexml, this change isn't reflected in the XML document.

To give an actual MCVF, I think this is sufficient to display the problem I'm experiencing:

from xml.dom import minidom

document_string = "<atag>Some text.</atag>"
document = minidom.parseString(document_string)

# documentElement is the "atag" object here.
document.documentElement.prefix = "pre"

# Expecting to see "<pre:atag>Some text.</pre:atag>"
print(document.toxml())  # instead prints the original document_string

You can demo it here. Thank you in advance!

1 Answers1

0

I was able to self-answer this.

element.tagName = "pre:" + element.tagName

It's apparently valid to just edit the whole tag, so I did, instead of trying to find an API call that'd do it for me. It took a lot of staring at documentation to figure this out. My code to change all of them now looks like:

def recursive_set_ns(root):
    # type: (Element) -> None
    """Set namespaces for all tags recursively by DFS."""
    if ":" not in root.tagName:  # leave existing namespaces alone
        root.tagName = "pre:" + root.tagName
    children = filter(lambda c: c.nodeType == c.ELEMENT_NODE, root.childNodes)
    for child_tag in children:
        recursive_set_ns(child_tag)