XML

时间:2017-09-08 08:02:40

标签: python xml soap lxml

我试图通过'请求'从python 3.4获取某些网络服务的数据。库。我需要获得一个有效的xml-string来解析' 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)

如何在没有符号的情况下提取数据,例如&#39;&gt;&#39;在XML内部?如果没有手动将&gt;符号替换为等效符号,这是否可行?

3 个答案:

答案 0 :(得分: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 :(得分:1)

可能有另一种方法可以做到这一点,但粗粒度的方法是创建一个你想要转换的字符表,只需替换它们;

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 entities

答案 2 :(得分:0)

您可以使用标准库的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 = {})

     

Unescape'&amp;','&lt;'和'&gt;'在一串数据中。

     

您可以通过将字典作为可选实体参数传递来取消其他数据字符串。键和值必须都是   串;每个密钥将替换为其相应的值。   '&amp; amp','&lt;'和'&gt;'即使实体是,也总是没有转义   提供。