【问题标题】:Python etree control empty tag formatPython etree 控制空标签格式
【发布时间】:2012-09-17 13:49:25
【问题描述】:

当使用 Python 的 etree 创建 XML 文件时,如果我们使用 SubElement 向文件写入一个空标签,我会得到:

<MyTag />

不幸的是,我们在 Fortran 中使用的 XML 解析器库不能处理这个问题,即使它是一个正确的标记。它需要看到:

<MyTag></MyTag>

有没有办法更改格式规则或 etree 中的其他内容以使其正常工作?

【问题讨论】:

    标签: python xml


    【解决方案1】:

    从 Python 3.4 开始,您可以对 tostring() functionElementTRee.write() method 使用 short_empty_elements 参数:

    >>> from xml.etree import ElementTree as ET
    >>> ET.tostring(ET.fromstring('<mytag/>'), short_empty_elements=False)
    b'<mytag></mytag>'
    

    在较旧的 Python 版本(2.7 到 3.3)中,作为一种变通方法,您可以使用 html 方法写出文档:

    >>> from xml.etree import ElementTree as ET
    >>> ET.tostring(ET.fromstring('<mytag/>'), method='html')
    '<mytag></mytag>'
    

    ElementTree.write() 方法和tostring() 函数都支持method 关键字参数。

    在更早的 Python 版本(2.6 及之前)上,您可以安装外部 ElementTree 库; 1.3 版支持该关键字。

    是的,这听起来有点奇怪,但是html 输出主要输出空元素作为开始和结束标记。一些元素最终仍然是空标签元素;特别是&lt;link/&gt;&lt;input/&gt;&lt;br/&gt; 等。尽管如此,还是升级您的 Fortran XML 解析器以实际解析符合标准的 XML!

    【讨论】:

    • 不幸的是,没有其他 Fortran XML 解析器可以使用,所以这是我们唯一的选择。谢谢!
    • 有没有办法维护标签的大小写?显然区分大小写也是一个问题,html 不保留大小写...
    • 不能拥有这一切...感谢您回答这个问题!
    • 如果我想在添加 End 标签后读取一个 XML 并写入另一个 XML,我该怎么做?
    • @Ac3_DeXt3R:这不是一个明确的问题。您的意思是写入另一个 XML file 吗?然后只需使用带有method 参数集的write 方法:ET.ElementTree(ET.fromstring('&lt;mytag/&gt;')).write(fileobj, method='html')
    【解决方案2】:

    添加一个空的text 是另一种选择:

    etree.SubElement(parent, 'child_tag_name').text=''
    

    但请注意,这不仅会改变文档的表示形式,还会改变文档的结构:即 child_el.text 将变为 '' 而不是 None

    哦,就像 Martijn 所说,尝试使用更好的库。

    【讨论】:

    • 这在 Python 2.7 中不起作用。它会忽略它,除非你真的写了一些东西,比如空格,' '
    【解决方案3】:

    如果你有 sed 可用,你可以通过管道输出你的 python 脚本到

    sed -e "s/<\([^>]*\) \/>/<\1><\/\1>/g"
    

    这将找到&lt;Tag /&gt; 的任何出现并将其替换为&lt;Tag&gt;&lt;/Tag&gt;

    【讨论】:

      【解决方案4】:

      这在 Python 3.4 中直接解决了。从那时起,xml.etree.ElementTree.ElementTreewrite 方法就有了short_empty_elements 参数:

      控制不包含内容的元素的格式。如果为 True(默认),则它们作为单个自闭合标签发出,否则它们作为一对开始/结束标签发出。

      更多详情请关注xml.etree documentation

      【讨论】:

        【解决方案5】:

        解释代码,我使用的ElementTree.py 版本在_write 方法中包含以下内容:

        write('<' + tagname)
        ...
        if node.text or len(node): # this line is literal
            write('>')
            ...
            write('</%s>' % tagname)
        else:
            write(' />')
        

        为了控制程序计数器,我创建了以下内容:

        class AlwaysTrueString(str):
            def __nonzero__(self): return True
        true_empty_string = AlwaysTrueString()
        

        然后我在那些 ElementTree 节点上设置node.text = true_empty_string,在这些节点上我想要一个打开-关闭标签而不是一个自关闭标签。

        “控制程序计数器”是指为库方法构造一组输入(在本例中为具有某种奇怪的真值测试的对象),以便库方法的调用以我的方式遍历其控制流图想要它。这非常脆弱:在新版本的库中,我的 hack 可能会崩溃——您可能应该将“可能”视为“几乎可以保证”。一般来说,不要打破抽象障碍。它在这里对我有用。

        【讨论】:

        • 这至少在 Python 2.7 中不起作用。我在导入下方添加了类,然后将true_empty_string 分配给节点的text,但什么也没发生。
        【解决方案6】:

        如果您有 python >=3.4,请使用 short_empty_elements=Falseoption 已在其他答案中显示,但是:

        1. 如果您已经拥有字符串形式的 XML 并且无法触摸代码 它是在哪里生成的..
        2. 如果您遇到 python 卡住的情况
        3. 如果您使用的是其他坚持使用自闭合标签的 XML 库..

        然后这个工作:

         xml = "<foo/><bar/>"
         xml = re.sub(r'<([^\/]+)\/\>', r'<\1></\1>', xml)
        
         print(xml)
        
         # output will be
         # <foo></foo><bar></bar>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-11
          • 2010-12-10
          • 2017-01-17
          相关资源
          最近更新 更多