【问题标题】:How to keep html tags when writing a ElementTree tree to disk?将 ElementTree 树写入磁盘时如何保留 html 标签?
【发布时间】:2021-10-22 22:29:10
【问题描述】:

我正在尝试使用 Python 的 xml.etree.ElementTree 将 XML 树写入磁盘,以重现给我的示例文档。目标 XML 文档中的字段如下所示:

<title>
This is a test of <br/> Hershey's <sup>&$174;</sup> chocolate factory machine <br/>
</title>

我的问题是,每当我尝试使用 ElementTree 的 .write() 方法将文本写入磁盘时,我都无法实现上述输出。 html 标签将被转换为&amp;lt;br&amp;gt;,或者商标符号(® 的东西)将显示为实际符号。有没有办法对我的文本进行编码以获得上述输出(其中商标由 ® 字符表示,但 html 是 html?)。我在 write 方法中尝试了不同的编码选项,但似乎没有任何效果。

编辑:这是一个最小的工作示例。获取一个输入 XML 模板文件,如:

<?xml version='1.0' encoding='UTF-8'?>
<document>
        <title> Text to replace </title>
</document>

我们尝试像这样修改文本

import xml.etree.ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()
to_sub_text = "This is a test of <br/> Hershey's <sup>&$174;</sup> chocolate factory machine"
spot = root.find('title')
spot.text = to_sub_text
tree.write('example_mod.xml', encoding='UTF-8', xml_declaration=True)

这将写入文件:

<?xml version='1.0' encoding='UTF-8'?>
<document>
        <title>This is a test of &lt;br/&gt; Hershey's &lt;sup&gt;&amp;$174;&lt;/sup&gt; chocolate factory machine</title>
</document>

正如我所说,我试图复制的文档将这些 html 标签作为标签。我的问题是:

  1. 我可以修改我的代码来做到这一点吗?
  2. 是否正在做这种良好的做法,还是保持现状更好(因此我需要与团队交谈,要求我以这种方式提供给他们)?

【问题讨论】:

  • 1) 请向我们展示您的代码。 2) "® stuff" 应该是这样的:&amp;#174;(带有#;)。
  • 谢谢。当我第一次发布时,我应该包含一个完整的示例。见上文。
  • &amp;$174; 应该是&amp;#174;
  • “html 标签将被转换为 <br>” - 当您将文本保存到 XML 文档时会发生这种情况。它将进行 XML 转义。文本偶然也是HTML源代码也无所谓。文字就是文字。如果要将实际节点的子树保存到 XML 元素,则需要创建它们。你不能做spot.text = 'a string with a couple of angle brackets' 期望得到与spot.text = 'literally any other string' 不同的待遇。
  • “或商标符号(将显示为实际符号。” - 是的。那又如何?XML 文件的工作是传输 字符(商标符号),不要保留您最喜欢的表示形式。&amp;#xae;&amp;#174;® 都表示相同的东西。从编写文件时的 XML 文档的角度来看 - 为什么使用6 个字符 (&amp;#174;) 什么时候可以用一个 (®)?

标签: python-3.x xml character-encoding elementtree


【解决方案1】:

spot.text = to_sub_text 分配不起作用。元素的text 属性仅包含纯文本。不能使用它来添加文本和子元素。

您可以做的是创建一个新的&lt;title&gt; 元素对象并将其附加到根:

import xml.etree.ElementTree as ET
 
tree = ET.parse('example.xml')
root = tree.getroot()
 
# Remove the old title element
old_title = root.find('title')
root.remove(old_title)
 
# Add a new title
new_title = "<title>This is a test of <br/> Hershey's <sup>&#174;</sup> chocolate factory machine</title>"
root.append(ET.fromstring(new_title))
 
# Prettify output (requires Python 3.9) 
ET.indent(tree)
 
# Use encoding='US-ASCII' to force output of character references for non-ASCII characters
tree.write('example_mod.xml', encoding='US-ASCII', xml_declaration=True)

example_mod.xml 中的输出:

<?xml version='1.0' encoding='US-ASCII'?>
<document>
  <title>This is a test of <br /> Hershey's <sup>&#174;</sup> chocolate factory machine</title>
</document>

【讨论】:

  • 谢谢。知道我不能使用这样的文本属性真的很有帮助,这是最接近我被要求复制的文档的过程。唯一的区别是,我被要求复制的文档中的编码标头说编码是&lt;?xml version="1.0" encoding="UTF-8"?&gt;。但是,如果我在写入步骤中将其指定为编码,则不会得到相同的输出(注册商标由符号表示)。您是否理解这基本上就是该编码类型必须采用的方式?
  • 目前我与客户的开发团队没有联系,因此我无法与他们交流他们如何阅读这些文档或如何制作它们(某些方面甚至可能手工制作!)。但我试图了解文档复制的哪些方面可以完成,以及哪些方面是基于我自己对不同编码方案等的无知。
  • 您是否理解这就是该编码类型的基本方式? 是的。 ® 字符和&amp;#174; 是完全相同事物的不同表示。对于 UTF-8,使用实际字符。
  • 顺便说一句,us-ascii 实际上是write() 方法中的默认编码。不必明确指定 (docs.python.org/3/library/…)。
  • 非常好,感谢您提供的信息。我被要求复制的文件当时一定是以一种有趣的方式创建的,因为 UTF-8 标题与该字符的表示是一致的。感谢您对此提供的所有帮助!
猜你喜欢
  • 2012-05-04
  • 2012-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-20
  • 1970-01-01
  • 2018-11-07
相关资源
最近更新 更多