python中的转义字符i

2024-09-29 23:25:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用以下源文件打印我的测试XML文件,但它无法正确处理非ASCII字符:

在xmltest.py公司名称:

import xml.sax.xmlreader
import xml.sax.saxutils

def testJunk(file, e2content):
  attr0 = xml.sax.xmlreader.AttributesImpl({})
  x =  xml.sax.saxutils.XMLGenerator(file)
  x.startDocument()
  x.startElement("document", attr0)

  x.startElement("element1", attr0)
  x.characters("bingo")
  x.endElement("element1")

  x.startElement("element2", attr0)
  x.characters(e2content)
  x.endElement("element2")

  x.endElement("document")
  x.endDocument()

如果我这么做

^{pr2}$

然后我得到一个xml文件,其中包含字符代码001。我想不出怎么摆脱这个角色。Firefox告诉我它不是格式良好的XML,并抱怨这个字符。我该怎么解决这个问题?在

澄清:我试图记录我无法控制的函数的输出,该函数输出非ASCII字符。在


更新:好的,所以现在我知道characters outside one of the accepted ranges不能以的形式进行编码。(或者更确切地说,它们可以被编码,但这无助于任何格式不好的w/r/t XML),但是如果我定义一种方法,它们可以被转义。在

(供将来参考:W3C在XML标准本身之外有a useful page,它说“应该用适当的标记替换控制代码”,但实际上并没有给出任何这样做的例子。)

如果我想用以下方式转义接受范围之外的字符:

在转义之前:(表示一个字符,而不是8个字符的字符串)

 abcdefghijkl

逃逸后:

 abcd<u>0001</u>efgh<u>0002</u>ijkl

我怎么能用python做到这一点呢?在

def escapeXML(src)
    dest = ??????
    return dest

Tags: 文件importdefasciixml字符saxcharacters
3条回答

"\001"aka“\x01”是ASCII控制代码。但它不是允许的XML字符之一。唯一的ASCII control codes which qualify是“\t”、“\n”和“\r”。在

示例:

>>> import xml.etree.cElementTree as ET
# Raw newline works
>>> t = ET.fromstring("<e>\n</e>")
>>> t.text
'\n'

# Hex escaping of a newline works
>>> t = ET.fromstring("<e>&#xa;</e>")
>>> t.text
'\n'

# Hex escaping of "\x01" doesn't work; it's not a valid XML character
>>> t = ET.fromstring("<e>&#x1;</e>")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 106, in XML
cElementTree.ParseError: reference to invalid character number: line 1, column 3

如果希望在XML文档中以某种方式包含无效的XML字符,则必须通过额外的转义级别将它们从XML解析器中隐藏起来。该机制需要被文档化、发布并被文档的读者理解。在

例如,在microsoftexcel2007+XLSX文件中,无效XML字符的Unicode代码点通过将它们表示为_xhhhh_hhhh是代码点的十六进制表示形式,从而被偷运通过解析器。在您的示例中,这将是7个字节_x0001_。注意,必须转义文本中的任何_字符,否则这些字符将被错误地解释为引入_xhhhh_序列。在

这是丑陋的,痛苦的,低效的,等等。你可以考虑其他方法。有必要使用XML吗?会是CSV文件(震惊,恐怖!)在你的申请中做得更好?在

编辑关于OP编码方案的一些注释:

A.虽然\r是一个有效的XML1.0输入字符,但它受mandatory immediate transmogrification的约束,因此您也应该对其进行转义。在

B.此方案假设/希望<u>hhhh</u>不能与任何其他标记混淆。在

我收回我上面所说的微软逃逸计划。它相对美观、无痛、高效。为了让温顺的读者了解你的计划,你应该展示一些必要的代码,以消除这些讨厌的部分,然后把它们粘在一起。请记住,MS方案需要某人编写一个转义函数和一个非转义函数,而您的方案需要对每个工具(SAX、DOM、ElementTree)进行不同的处理。在

D.在细节层面,代码有点模糊:

if (len(g1) > 0):应该是if g1:

if (not foo == None):与普遍接受的习惯用法有三个偏差:(1)括号(2)not x == y而不是{}(3)!= None而不是{}

不要使用list(以及其他内置对象的名称)作为自己变量的名称。在

编辑2要使用正则表达式拆分字符串。为什么不使用re.split?在

^{pr2}$

这似乎对我有用。在

r = re.compile(ur'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\xFF' \
  + ur'\u0100-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]')
def escapeInvalidXML(string):
  def replacer(m):
    return "<u>"+('%04X' % ord(m.group(0)))+"</u>"
  return re.sub(r,replacer,string)

示例:

^{pr2}$

字符范围从http://www.w3.org/TR/2006/REC-xml-20060816/#charsets,我没有逃过所有内容,只是下面的\uFFFF。在


更新:哎呀,忘了适应SAX的startElement/characters方法,正确处理多行代码:

import re
import xml.sax.xmlreader
import xml.sax.saxutils

r = re.compile(ur'(.*?)(?:([^\x09\x0A\x0D\x20-\x7E\x85\xA0-\xFF' \
    + ur'\u0100-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD])|([\n])|$)')
attr0 = xml.sax.xmlreader.AttributesImpl({})
def splitInvalidXML(string):
    list = []
    def replacer(m):
        g1 = m.group(1)
        if (len(g1) > 0):
            list.append(g1)
        g2 = m.group(2)
        if (not g2 == None):
            list.append(ord(g2))
        g3 = m.group(3)
        if (not g3 == None):
            list.append(g3)
        return ""
    re.sub(r,replacer,string)
    return list

def submitCharacters(x, string):
    for fragment in splitInvalidXML(string):
        if (isinstance(fragment,int)):
            x.startElement("u", attr0)
            x.characters('%04X' % fragment)
            x.endElement("u")
        else:
            x.characters(fragment)

def test1(fname):
    with open(fname,'w') as f:
        x = xml.sax.saxutils.XMLGenerator(f)
        x.startDocument()
        x.startElement('document',attr0)
        submitCharacters(x, 'this is a \x01 test\nof the \x02\x0b xml system.')
        x.endElement('document')
        x.endDocument()

test1('test.xml')

这会产生:

<?xml version="1.0" encoding="iso-8859-1"?>
<document>this is a <u>0001</u> test
of the <u>0002</u><u>000B</u> xml system.</document>

这个https://bugs.python.org/issue5166有一个开放的python错误-还不确定解决方案是什么/是否会被修复,因为它已经打开了一段时间,但是值得定期检查一下,以防我们找到一个正确的解决方案来处理python本身内置的无效XML字符。在

相关问题 更多 >

    热门问题