我正在使用Python的xml.dom.minidom
来创建XML文档。 (逻辑结构 - > XML字符串,而不是相反。)
如何让它逃脱我提供的字符串,这样他们就无法搞砸XML?
答案 0 :(得分:65)
这样的东西?
>>> from xml.sax.saxutils import escape
>>> escape("< & >")
'< & >'
答案 1 :(得分:12)
你的意思是你做这样的事情:
from xml.dom.minidom import Text, Element
t = Text()
e = Element('p')
t.data = '<bar><a/><baz spam="eggs"> & blabla &entity;</>'
e.appendChild(t)
然后你将得到很好的转义XML字符串:
>>> e.toxml()
'<p><bar><a/><baz spam="eggs"> & blabla &entity;</></p>'
答案 2 :(得分:11)
xml.sax.saxutils.escape
仅会转义&
,<
和>
,但它会提供entities
参数以额外转义其他字符串:
from xml.sax.saxutils import escape
def xmlescape(data):
return escape(data, entities={
"'": "'",
"\"": """
})
xml.sax.saxutils.escape
在内部使用str.replace()
,因此您也可以跳过导入并编写自己的函数,如MichealMoser的回答所示。
答案 3 :(得分:9)
xml.sax.saxutils不会转义引号字符(“)
所以这是另一个:
def escape( str ):
str = str.replace("&", "&")
str = str.replace("<", "<")
str = str.replace(">", ">")
str = str.replace("\"", """)
return str
如果你查找它,那么xml.sax.saxutils只会执行字符串替换
答案 4 :(得分:4)
如果您不希望其他项目导入,并且您已经拥有cgi
,则可以使用此项:
>>> import cgi
>>> cgi.escape("< & >")
'< & >'
但请注意,由于此代码易读性受到影响 - 您可能应该将其放在一个函数中以更好地描述您的意图:(并在您使用时为其编写单元测试;)
def xml_escape(s):
return cgi.escape(s) # escapes "<", ">" and "&"
答案 5 :(得分:2)
xml_special_chars = {
"<": "<",
">": ">",
"&": "&",
"'": "'",
'"': """,
}
xml_special_chars_re = re.compile("({})".format("|".join(xml_special_chars)))
def escape_xml_special_chars(unescaped):
return xml_special_chars_re.sub(lambda match: xml_special_chars[match.group(0)], unescaped)
所有魔术都发生在re.sub()
中:参数repl
不仅接受字符串,还接受函数。
答案 6 :(得分:1)
Andrey Vlasovskikh 接受的答案是对 OP 最完整的答案。但是这个主题出现在最频繁的 /div//text()
搜索中,我想对所讨论的三种解决方案进行时间比较
在本文中以及提供第四个选项,我们选择部署,因为它提供了增强的性能。
所有四个都依赖于原生 python 数据处理或 python 标准库。解决方案按性能从最慢到最快的顺序提供。
选项 1 - 正则表达式
此解决方案使用 python 正则表达式库。它产生最慢的性能:
python escape xml
仅供参考:µs 是微秒的符号,即百万分之一秒。另一个实现的完成时间以纳秒 (ns) 为单位,即十亿分之一秒。
选项 2 -- xml.sax.saxutils
此解决方案使用 python import re
table = {
"<": "<",
">": ">",
"&": "&",
"'": "'",
'"': """,
}
pat = re.compile("({})".format("|".join(table)))
def xmlesc(txt):
return pat.sub(lambda match: table[match.group(0)], txt)
>>> %timeit xmlesc('<&>"\'')
1.48 µs ± 1.73 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
库。
xml.sax.saxutils
选项 3 - str.replace
此解决方案使用字符串 from xml.sax.saxutils import escape
def xmlesc(txt):
return escape(txt, entities={"'": "'", '"': """})
>>> %timeit xmlesc('<&>"\'')
832 ns ± 4.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
方法。在底层,它实现了与 python 的 replace()
类似的逻辑。 saxutils 代码有一个 for 循环,它会消耗一些性能,使这个版本稍微快一些。
xml.sax.saxutils
选项 4 - str.translate
这是最快的实现。它使用字符串 def xmlesc(txt):
txt = txt.replace("&", "&")
txt = txt.replace("<", "<")
txt = txt.replace(">", ">")
txt = txt.replace('"', """)
txt = txt.replace("'", "'")
return txt
>>> %timeit xmlesc('<&>"\'')
503 ns ± 0.725 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
方法。
translate()