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

7

我需要转义一个无效的 XML 文件中的特殊字符,该文件大约有 5000 行。这里是我要处理的 XML 示例:

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

问题出在名称中的特殊字符"&"。您如何使用Python库转义此类特殊字符?我没有找到一种使用BeautifulSoup进行转义的方法。

4个回答

10

如果您不关心XML中的无效字符,可以使用XML解析器的 recover选项(请参见使用lxml.etree.iterparse解析破碎的XML):

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>

2
最后我使用了lxml.html.soupparser中的parse方法:它可以解析我的丑陋的XML而不会出错 :) 谢谢你的回答。 - Jérôme Pigeot
2
这个答案虽然有用,但是它不会转义未转义的字符。它似乎只会将它们丢弃。 - Asclepius

1

你可能只是想在将HTML传递给BeautifulSoup之前对其进行一些简单的正则表达式操作。

更简单的方法是,如果代码中没有任何SGML实体(&...;),html=html.replace('&','&amp;')就可以解决问题。

否则,请尝试以下方法:

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

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


0

这个答案提供了XML清理函数,虽然它们不会转义未转义的字符,而是直接删除它们。

使用bs4和lxml

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

import xml.etree.ElementTree

import bs4


def sanitize_xml(content: bytes) -> bytes:
    # Ref: https://dev59.com/U1TTa4cB1Zd3GeqPqj-S#57450722/
    try:
        xml.etree.ElementTree.fromstring(content)
    except xml.etree.ElementTree.ParseError:
        return bs4.BeautifulSoup(content, features='lxml-xml').encode()
    return content  # already valid XML

仅使用lxml

显然,当可以仅使用lxml时,同时使用bs4lxml没有太大意义。这个lxml==4.4.0使用的清理函数本质上是从jfs的答案中派生出来的。

import lxml.etree


def sanitize_xml(content: bytes) -> bytes:
    # Ref: https://dev59.com/U1TTa4cB1Zd3GeqPqj-S#57450722/
    try:
        lxml.etree.fromstring(content)
    except lxml.etree.XMLSyntaxError:
        root = lxml.etree.fromstring(content, parser=lxml.etree.XMLParser(recover=True))
        return lxml.etree.tostring(root)
    return content  # already valid XML

-1
<name>name & surname</name>

不是格式良好的XML。应该是:

<name>name &amp; surname</name>

所有符合标准的 XML 工具都应该创建这个 - 通常你不必担心。如果你创建了一个带有 '&' 字符的字符串,那么 XML 工具将输出转义版本。如果你手动创建字符串,则需要确保它已经被转义。如果你使用 XML 编辑器,它应该会为你转义。

如果文件是由别人给你的,请将其退回并告诉他们它不是格式良好的。如果他们已经不存在了,你将不得不使用纯文本编辑器。这很脆弱和混乱,但没有其他办法。如果文件中有其他用于转义的 & 符号,则该文件是垃圾。

参见10年前的帖子这里和稍后的帖子这里


XML是由Novell工具Metamig生成的:它从NSS服务器导出受托人。有一些文件夹中包含&字符,因此我必须转义所有这些字符以正确解析文件。 - Jérôme Pigeot
假设你引用正确,那么这是伪XML。我不知道这个工具,但如果你报告正确,它永远不应该被发布。这是错误的。如果你为此付费了,要求退款。 - peter.murray.rust
谢谢Peter,我不知道在正确的XML文件中'&'应该被转义。你帮我省去了研究为什么Python ElementTree没有显示'&'字符的时间。 - lorenzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接