【发布时间】:2012-09-17 13:49:25
【问题描述】:
当使用 Python 的 etree 创建 XML 文件时,如果我们使用 SubElement 向文件写入一个空标签,我会得到:
<MyTag />
不幸的是,我们在 Fortran 中使用的 XML 解析器库不能处理这个问题,即使它是一个正确的标记。它需要看到:
<MyTag></MyTag>
有没有办法更改格式规则或 etree 中的其他内容以使其正常工作?
【问题讨论】:
当使用 Python 的 etree 创建 XML 文件时,如果我们使用 SubElement 向文件写入一个空标签,我会得到:
<MyTag />
不幸的是,我们在 Fortran 中使用的 XML 解析器库不能处理这个问题,即使它是一个正确的标记。它需要看到:
<MyTag></MyTag>
有没有办法更改格式规则或 etree 中的其他内容以使其正常工作?
【问题讨论】:
从 Python 3.4 开始,您可以对 tostring() function 和 ElementTRee.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 输出主要输出空元素作为开始和结束标记。一些元素最终仍然是空标签元素;特别是<link/>、<input/>、<br/> 等。尽管如此,还是升级您的 Fortran XML 解析器以实际解析符合标准的 XML!
【讨论】:
html 不保留大小写...
method 参数集的write 方法:ET.ElementTree(ET.fromstring('<mytag/>')).write(fileobj, method='html')。
添加一个空的text 是另一种选择:
etree.SubElement(parent, 'child_tag_name').text=''
但请注意,这不仅会改变文档的表示形式,还会改变文档的结构:即 child_el.text 将变为 '' 而不是 None。
哦,就像 Martijn 所说,尝试使用更好的库。
【讨论】:
' '。
如果你有 sed 可用,你可以通过管道输出你的 python 脚本到
sed -e "s/<\([^>]*\) \/>/<\1><\/\1>/g"
这将找到<Tag /> 的任何出现并将其替换为<Tag></Tag>
【讨论】:
这在 Python 3.4 中直接解决了。从那时起,xml.etree.ElementTree.ElementTree 的write 方法就有了short_empty_elements 参数:
控制不包含内容的元素的格式。如果为 True(默认),则它们作为单个自闭合标签发出,否则它们作为一对开始/结束标签发出。
更多详情请关注xml.etree documentation。
【讨论】:
解释代码,我使用的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 可能会崩溃——您可能应该将“可能”视为“几乎可以保证”。一般来说,不要打破抽象障碍。它在这里对我有用。
【讨论】:
true_empty_string 分配给节点的text,但什么也没发生。
如果您有 python >=3.4,请使用 short_empty_elements=Falseoption 已在其他答案中显示,但是:
然后这个工作:
xml = "<foo/><bar/>"
xml = re.sub(r'<([^\/]+)\/\>', r'<\1></\1>', xml)
print(xml)
# output will be
# <foo></foo><bar></bar>
【讨论】: