使用Python转义XML中未转义的字符

使用Python转义XML中未转义的字符,python,xml,beautifulsoup,lxml,special-characters,Python,Xml,Beautifulsoup,Lxml,Special Characters,我需要转义一个大约5000行长的无效XML文件中的特殊字符。下面是我必须处理的XML示例: <root> <element> <name>name & surname</name> <mail>name@name.org</mail> </element> </root> 姓名 name@name.org 这里的问题是名称中的字符“&”。如何使用Python库转义像这样的特殊

我需要转义一个大约5000行长的无效XML文件中的特殊字符。下面是我必须处理的XML示例:

<root>
 <element>
  <name>name & surname</name>
  <mail>name@name.org</mail>
 </element>
</root>

姓名
name@name.org
这里的问题是名称中的字符“&”。如何使用Python库转义像这样的特殊字符?我没有找到一种方法来处理它。

姓名和姓氏
不是格式良好的XML。应该是:

<name>name &amp; surname</name>
name&;姓
所有符合规范的XML工具都应该创建这个——您通常不必担心。如果您创建了一个带有“&”字符的字符串,那么XML工具将输出转义版本。如果您手工创建字符串,您有责任确保它被转义。如果您使用XML编辑器,它应该为您转义

如果文件是别人给你的,把它发回去告诉他们格式不好。如果它们不再存在,则必须使用纯文本编辑器。这是脆弱和混乱的,但没有其他办法。如果文件的其他位置有用于转义的符号,则该文件是垃圾


看一篇10年前的文章和一篇后来的文章

您可能只是想在将HTML放入BeautifulSoup之前对其进行一些简单的正则表达式

更简单的是,如果代码中没有任何SGML实体(
&…;
),那么
html=html.replace('&','&;')
就可以了

否则,请尝试以下操作:

x ="<html><h1>Fish & Chips & Gravy</h1><p>Fish &amp; Chips &#x0026; Gravy</p>"
import re
q=re.sub(r'&([^a-zA-Z#])',r'&amp;\1',x)
print q
x=“炸鱼薯条和肉汁炸鱼薯条和肉汁”
进口稀土
q=re.sub(r'&([^a-zA-Z#]),r'&;\1',x)
打印q

基本上,正则表达式查找的是
&
,后面不跟字母数字或#字符。它不会处理行尾的符号,但这可能是可以修复的。

如果您不关心xml中的无效字符,可以使用xml解析器的
恢复
选项(请参阅):

输出

姓名
name@name.org

这个答案提供了XML消毒器函数,尽管它们不会转义未转义的字符,而是简单地删除它们

将bs4与lxml一起使用 这个问题想知道如何使用Beautiful Soup。这里有一个函数,它将用它清理一个小的XML
bytes
对象。使用包装要求
beautifulsoup4==4.8.0
lxml==4.4.0
对其进行测试。请注意,
bs4
在此要求使用
lxml

import xml.etree.ElementTree
进口bs4
def sanitize_xml(内容:字节)->字节:
#参考:https://stackoverflow.com/a/57450722/
尝试:
xml.etree.ElementTree.fromstring(内容)
除xml.etree.ElementTree.ParseError外:
返回bs4.BeautifulSoup(content,features='lxml').encode()
返回内容#已经是有效的XML
仅使用lxml 显然,如果单独使用
lxml
就可以做到这一点,那么同时使用
bs4
lxml
没有多大意义。此使用消毒剂功能的
lxml==4.4.0
基本上源自

导入lxml.etree
def sanitize_xml(内容:字节)->字节:
#参考:https://stackoverflow.com/a/57450722/
尝试:
lxml.etree.fromstring(内容)
除lxml.etree.XMLSyntaxError外:
root=lxml.etree.fromstring(内容,解析器=lxml.etree.XMLParser(recover=True))
返回lxml.etree.tostring(根)
返回内容#已经是有效的XML

xml是由一个名为metamig的novell工具生成的:它从nss服务器导出受托人:有带有&字符的文件夹,因此我必须转义所有这些文件夹才能正确解析文件,如果您正确引用了它,则它是伪xml。我不知道这个工具,但如果你报告正确的话,它就永远不会出来。这是错误的。如果你付了钱,就要求退款。谢谢你,彼得,我不知道“&”应该在正确的XML文件中转义。您为我省去了一项关于Python ElementTree为什么没有显示“&”字符的研究。最后,我使用了lxml.html.soupparser中的解析方法:它可以解析我难看的xml,而无需哭喊:)谢谢您的回答。这个答案虽然有用,但不会避开未替换的字符。很明显,它只是简单地放弃它们。
x ="<html><h1>Fish & Chips & Gravy</h1><p>Fish &amp; Chips &#x0026; Gravy</p>"
import re
q=re.sub(r'&([^a-zA-Z#])',r'&amp;\1',x)
print q
from lxml import etree

parser = etree.XMLParser(recover=True) # recover from bad characters.
root = etree.fromstring(broken_xml, parser=parser)
print etree.tostring(root)
<root>
<element>
<name>name  surname</name>
<mail>name@name.org</mail>
</element>
</root>