【问题标题】:Python: specify XMLNS on xml.etree elementsPython:在 xml.etree 元素上指定 XMLNS
【发布时间】:2014-02-26 10:52:38
【问题描述】:

在我的 Python 代码中,我目前正在使用 xml.etree 库来创建一棵树,然后将其转储到 XML 字符串中。不幸的是,我不能使用 Python 标准库中的模块以外的模块来执行此操作。

这是我的代码:

import xml.etree.ElementTree as ET

def dump_to_XML():
  root_node = ET.Element("root")
  c1_node = ET.SubElement(root_node, "child1")
  c1_node.text = "foo"
  c2_node = ET.SubElement(root_node, "child2")
  gc1_node = ET.SubElement(c2_node, "grandchild1")
  gc1_node.text = "bar"
  return ET.tostring(root_node, encoding='utf8', method='xml')

给出字符串:

<?xml version='1.0' encoding='utf8'?>
<root>
    <child1>foo</child1>
    <child2>
        <grandchild1>bar</grandchild1>
    </child2>
</root>

现在,我有两个架构文件位于 - 比如 - http://myhost.com/p.xsdhttp://myhost.com/q.xsd,我希望将输出字符串转换为:

<?xml version='1.0' encoding='UTF-8'?>
<root xmlns:p="http://myhost.com/p.xsd" xmlns:q="http://myhost.com/q.xsd">
    <p:child1>foo</p:child1>
    <p:child2>
        <q:grandchild1>bar</q:grandchild1>
    </p:child2>
</root>

我如何利用etree 库来实现这一目标?

提前致谢

【问题讨论】:

    标签: python schema xml-namespaces elementtree


    【解决方案1】:

    我们开始吧:

    import xml.etree.ElementTree as ET
    
    xmlns_uris = {'p': 'http://myhost.com/p.xsd',
                  'q': 'http://myhost.com/q.xsd'}
    
    def dump_to_XML():
      root_node = ET.Element("root")
      c1_node = ET.SubElement(root_node, "child1")
      c1_node.text = "foo"
      c2_node = ET.SubElement(root_node, "child2")
      gc1_node = ET.SubElement(c2_node, "grandchild1")
      gc1_node.text = "bar"
      annotate_with_XMLNS_prefixes(gc1_node, 'q', False)
      annotate_with_XMLNS_prefixes(root_node, 'p')
      add_XMLNS_attributes(root_node, xmlns_uris)
      return ET.tostring(root_node, encoding='UTF-8', method='xml')
    
    def annotate_with_XMLNS_prefixes(tree, xmlns_prefix, skip_root_node=True):
        if not ET.iselement(tree):
            tree = tree.getroot()
        iterator = tree.iter()
        if skip_root_node: # Add XMLNS prefix also to the root node?
            iterator.next()
        for e in iterator:
            if not ':' in e.tag:
                e.tag = xmlns_prefix + ":" + e.tag
    
    def add_XMLNS_attributes(tree, xmlns_uris_dict):
        if not ET.iselement(tree):
            tree = tree.getroot()
        for prefix, uri in xmlns_uris_dict.items():
            tree.attrib['xmlns:' + prefix] = uri
    

    执行:print dump_to_XML() 给出:

    <?xml version='1.0' encoding='UTF-8'?>
    <root xmlns:p="http://myhost.com/p.xsd" xmlns:q="http://myhost.com/q.xsd">
        <p:child1>foo</p:child1>
        <p:child2>
            <q:grandchild1>bar</q:grandchild1>
        </p:child2>
    </root>
    

    【讨论】:

    • def add_XMLNS_attributes(tree, xmlns_uris_dict): if not ET.iselement(tree): tree = tree.getroot() for prefix, uri in xmlns_uris_dict.items(): if prefix in ['']: tree.attrib['xmlns' + prefix] = uri else: tree.attrib['xmlns:' + prefix] = uri 这使得空字符串被格式化为谷歌所需的 xmlns=uri
    【解决方案2】:
    from lxml import etree
    xmlns_uris = {'p': 'http://myhost.com/p.xsd', 'q': 'http://myhost.com/q.xsd'}
    
    root = etree.Element('root', nsmap = xmlns_uris)
    child1 = etree.SubElement(root,'{%s}child1'%xmlns_uris['p'])
    child1.text = 'foo'
    
    child2 = etree.SubElement(root,'{%s}child2'%xmlns_uris['p'])
    grandchild1 = etree.SubElement(child2,'{%s}grandchild1'%xmlns_uris['q'])
    grandchild1.text = 'bar'
    
    print(etree.tostring(root, pretty_print=True, encoding='UTF-8', xml_declaration=True).decode('cp1251'))
    

    【讨论】:

    • 您好,请使用您的代码编辑并发布解释,并告诉我们为什么它是正确答案
    猜你喜欢
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    • 2017-04-05
    • 1970-01-01
    • 2021-12-27
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多