XML中存在错误的编码符号

4

我正在尝试使用Python 3.4通过“requests”库从某些网络服务获取数据。我需要获取一个有效的XML字符串,以便使用“lxml”库进行解析。但由于某种原因,XML中的数据未正确编码:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
         <xmlData>
         &lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;Response&gt;&lt;Data&    gt;&lt;Company&gt;... etc.
         </xmlData>
    </soap:Body>
</soap:Envelope>

使用以下代码:
ssession = requests.Session()
session.get(target_url)
exml = session.post(target_url, data=__xml, headers=headers)
print(exml.text)

如何在XML中提取不带符号“>”的数据?是否可以在不手动替换&gt;符号为其等效项的情况下实现?

3个回答

2

也许还有其他方法,但是一种粗略的方法是创建一个字符转换表,然后只需替换它们即可。

replacements = {
    "&gt;" : ">",
    "&lt;" : "<"
    }

def replace(xml):
    repl_str = xml
    for char in replacements:
        repl_str = repl_str.replace(char, replacements[char])
    return repl_str

添加注释:这里可以找到一个小表格 w3schools实体字符


根据W3C标准,此操作将不会生成有效的XML,因为开头声明在文档中重复:<?xml ... ?>,导致XML格式不规范。请记住,XML不是一个简单的文本文件,而是遵循标记规则的。 - Parfait

2

目前您的SOAP响应是有效的、格式良好的XML。字符实体的原因是因为您有一个嵌入式XML文档,因此实际标记不能显示该内部XML,以便整个响应保持有效。

只需解析嵌入式XML,将其编码为字节对象以接受特殊声明字符,并在其自己的XML树中解析即可。

from io import BytesIO
import lxml.etree as ET

# same SOAP response code...

# ORIGINAL TREE
soap_doc = ET.parse(BytesIO(exml.text.encode('utf-8')))
embedded_data = soap_doc.findall(".//xmlData")[0].text.strip().encode('utf-8')

# NEW TREE
tree = ET.parse(BytesIO(embedded_data))

# OUTPUT TO FILE
with open('output.xml', 'wb') as f:
    f.write(ET.tostring(tree, xml_declaration=True, 
                        pretty_print=True, encoding='utf-8'))

#<?xml version='1.0' encoding='utf-8'?>
#<Response>
#  <Data>
#    <Company> </Company>
#  </Data>
#</Response>

上面的代码针对这个字符串进行了测试,它完成了一个有效的<xmlData>,因为OP省略了嵌入的XML的其余部分:

'''<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
         <xmlData>
          &lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;Response&gt;&lt;Data&gt;&lt;Company&gt; &lt;/Company&gt;&lt;/Data&gt;&lt;/Response&gt;
         </xmlData>
    </soap:Body>
</soap:Envelope>
'''

1
您可以使用标准库的sax包中的unescape函数。
>>> from xml.sax.saxutils import unescape
>>> escaped = """&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;Response&gt;&lt;Data&gt;&lt;Company&gt;"""
>>> unescape(escaped)
'<?xml version="1.0" encoding="UTF-8"?><Response><Data><Company>'

unescape 默认处理 & 和 < 和 > 字符;你可以传递一个字典来处理其他字符。参见 docs:

xml.sax.saxutils.unescape(data, entities={})

在字符串中反转义 '&', '<', 和 '>'。

通过将可选的 entities 参数作为字典传递,您可以对其他字符串进行反转义。键和值必须全部是字符串;每个键都将被其相应的值替换。 '&amp', '<', 和 '>' 总是被反转义,即使提供了 entities。


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