Suppressing namespace prefixes in ElementTree 1.2

落花浮王杯 提交于 2019-11-30 04:41:40

After looking at the source code for ElementTree in python2.6, the : is hard coded in the fixtag function. As a workaround, here's what I did:

from xml.etree import ElementTree as etree

if etree.VERSION[0:3] == '1.2':
    #in etree < 1.3, this is a workaround for supressing prefixes

    def fixtag(tag, namespaces):
        import string
        # given a decorated tag (of the form {uri}tag), return prefixed
        # tag and namespace declaration, if any
        if isinstance(tag, etree.QName):
            tag = tag.text
        namespace_uri, tag = string.split(tag[1:], "}", 1)
        prefix = namespaces.get(namespace_uri)
        if namespace_uri not in namespaces:
            prefix = etree._namespace_map.get(namespace_uri)
            if namespace_uri not in etree._namespace_map:
                prefix = "ns%d" % len(namespaces)
            namespaces[namespace_uri] = prefix
            if prefix == "xml":
                xmlns = None
            else:
                if prefix is not None:
                    nsprefix = ':' + prefix
                else:
                    nsprefix = ''
                xmlns = ("xmlns%s" % nsprefix, namespace_uri)
        else:
            xmlns = None
        if prefix is not None:
            prefix += ":"
        else:
            prefix = ''

        return "%s%s" % (prefix, tag), xmlns

    etree.fixtag = fixtag
    etree._namespace_map['http://some.namespace'] = None
else:
    #For etree > 1.3, use register_namespace function
    etree.register_namespace('', 'http://some.namespace')

In case this post ever gets out of date, the code is maintained here.

I created a method at the top of my file and simply use it where the tag string should be. I named it 'ns_tag', but you could name it whatever you want.

def ns_tag(tag):
    return str( ElementTree.QName('http://some.namespace/api/4/', tag) )

Example:

root = ElementTree.fromstring(xml)
success = root.find(ns_tag('success'))
if success.text == 'true':
    for node in root.find(ns_tag('items')):
        id = node.find(ns_tag('id')).text
        ...

For removing namespace from tags, I use this code where a taget object is a subclass of TreeBuilder. In both methods start and end, we remove the unwanted namespace.

from xml.etree.ElementTree import XML, XMLParser, tostring, TreeBuilder

class StripNamespace(TreeBuilder):
    def start(self, tag, attrib):
        index = tag.find('}')
        if index != -1:
            tag = tag[index+1:]
        super(StripNamespace, self).start(tag, attrib)
    def end(self, tag):
        index = tag.find('}')
        if index != -1:
            tag = tag[index+1:]
        super(StripNamespace, self).end(tag)

target = StripNamespace()
parser = XMLParser(target=target)
with open("DmsDesc.xml") as f:
    content = f.read()
root = XML(content, parser=parser)
print tostring(root)

Simple and pretty.

It's a hack, but this worked well for me on Jython 2.5.2

    ns=re.match('^\{([^\}]+)\}', mydoc.getroot().tag ).group(1)
    etree._namespace_map[ns]='STRIPME'
    etree.tostring( mydoc.getroot() ).replace( 'STRIPME:', '' )
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!