【发布时间】:2021-08-11 11:21:35
【问题描述】:
我正在向 API 发送查询并接收 xml 响应,我想将其解析为数据帧。我最近遇到了 pd.read_xml 选项,到目前为止已经尝试了一些,但似乎无法使其正常工作。
我的 xml 看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<html>
<body>
<searchretrieveresponse xmlns="http://www.loc.gov/zing/srw/">
<version>
1.1
</version>
<numberofrecords>
1
</numberofrecords>
<records>
<record>
<recordschema>
oai_dc
</recordschema>
<recordpacking>
xml
</recordpacking>
<recorddata>
<dc xmlns="http://www.openarchives.org/OAI/2.0/oai_dc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dnb="http://d-nb.de/standards/dnbterms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dc:title>
[Erg.-H.]. Myst IV Revelation
</dc:title>
<dc:date>
2004
</dc:date>
<dc:identifier xmlns:tel="http://krait.kb.nl/coop/tel/handbook/telterms.html" xsi:type="tel:ISBN">
978-3-8272-9125-7 kart. : EUR 16.95, EUR 17.50 (AT)
</dc:identifier>
<dc:identifier xmlns:tel="http://krait.kb.nl/coop/tel/handbook/telterms.html" xsi:type="tel:ISBN">
3-8272-9125-9 kart. : EUR 16.95, EUR 17.50 (AT)
</dc:identifier>
<dc:identifier xsi:type="dnb:IDN">
97274004X
</dc:identifier>
<dc:format>
32 S.
</dc:format>
<dc:relation>
http://d-nb.info/973086416
</dc:relation>
</dc>
</recorddata>
<recordposition>
1
</recordposition>
</record>
</records>
<nextrecordposition>
2
</nextrecordposition>
<echoedsearchretrieverequest>
<version>
1.1
</version>
<query>
978-3-8272-9125-7
</query>
<xquery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true">
</xquery>
<recordschema>
oai_dc
</recordschema>
</echoedsearchretrieverequest>
</searchretrieveresponse>
</body>
</html>
这是我在 Jupyter Notebook 中漂亮打印后复制粘贴的 API 响应。
如果我只是通过 print(r1.content) 打印响应,我会得到以下信息:
b'<?xml version="1.0" encoding="UTF-8"?>\n<searchRetrieveResponse xmlns="http://www.loc.gov/zing/srw/"><version>1.1</version><numberOfRecords>1</numberOfRecords><records><record><recordSchema>oai_dc</recordSchema><recordPacking>xml</recordPacking><recordData><dc xmlns:dnb="http://d-nb.de/standards/dnbterms" xmlns="http://www.openarchives.org/OAI/2.0/oai_dc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\n <dc:title>[Erg.-H.]. Myst IV Revelation</dc:title>\n <dc:date>2004</dc:date>\n <dc:identifier xmlns:tel="http://krait.kb.nl/coop/tel/handbook/telterms.html" xsi:type="tel:ISBN">978-3-8272-9125-7 kart. : EUR 16.95, EUR 17.50 (AT)</dc:identifier>\n <dc:identifier xmlns:tel="http://krait.kb.nl/coop/tel/handbook/telterms.html" xsi:type="tel:ISBN">3-8272-9125-9 kart. : EUR 16.95, EUR 17.50 (AT)</dc:identifier>\n <dc:identifier xsi:type="dnb:IDN">97274004X</dc:identifier>\n <dc:format>32 S.</dc:format>\n <dc:relation>http://d-nb.info/973086416</dc:relation>\n</dc></recordData><recordPosition>1</recordPosition></record></records><nextRecordPosition>2</nextRecordPosition><echoedSearchRetrieveRequest><version>1.1</version><query>978-3-8272-9125-7</query><xQuery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/><recordSchema>oai_dc</recordSchema></echoedSearchRetrieveRequest></searchRetrieveResponse>'
我用下面的代码取得了一些成功:
df = pd.read_xml(r1.content, namespaces={"xmlns":"http://www.openarchives.org/OAI/2.0/oai_dc/",
"dc": "http://purl.org/dc/elements/1.1/",
"dnb": "http://d-nb.de/standards/dnbterms",
"xsi": "http://www.w3.org/2001/XMLSchema-instance"})
但是,当我收到这样的数据框时,这似乎只考虑了顶层:
version numberOfRecords record nextRecordPosition query xQuery recordSchema
0 1.1 NaN NaN NaN None NaN None
1 NaN 15315.0 NaN NaN None NaN None
2 NaN NaN NaN NaN None NaN None
3 NaN NaN NaN 11.0 None NaN None
4 1.1 NaN NaN NaN Händel NaN oai_dc
由于我对 API 返回的实际“记录”感兴趣,因此我尝试了以下方法:
df = pd.read_xml(r1.content, xpath='.//records', namespaces={"xmlns":"http://www.openarchives.org/OAI/2.0/oai_dc/",
"dc": "http://purl.org/dc/elements/1.1/",
"dnb": "http://d-nb.de/standards/dnbterms",
"xsi": "http://www.w3.org/2001/XMLSchema-instance"})
但我得到一个错误:ValueError: xpath does not return any nodes. Be sure row level nodes are in xpath. If document uses namespaces denoted with xmlns, be sure to define namespaces and use them in xpath.
最后,尤其是对于包含多条记录的响应,我想要的是一个列出记录内容的数据框。所以它应该看起来像:
dc:title dc:date dc:identifier
0 [Erg.-H.]. Myst IV Revelation 2004 978-3-8272-9125-7 kart. : EUR 16.95, EUR 17.50 (AT)
据我所知,我已经添加了所有命名空间,并且我还尝试将 xpath 设置为查找“record”而不是“records”,甚至是“dc:title”,但到目前为止,我总是以添加 xpath 属性后立即显示错误消息。我究竟做错了什么?我怀疑它与正确的命名空间有关,但无法弄清楚它是什么......非常感谢任何帮助!
【问题讨论】:
-
您问题中的示例 xml 格式不正确。您能否编辑问题并验证您有一个简化的、格式正确的 xml 示例以及该示例的预期输出?这将使尝试回答变得更加容易。
-
您好,谢谢您,我现在已经在文本中包含了关于 xml-response 的解释并对其进行了一些编辑 - 它确实应该是格式正确的,但我没有复制整个内容,而是只是开始。
-
还没有。首先,您仍然需要添加所需输出的样本。其次,您应该通过 XML 验证器 (for example, this one) 运行您的 xml 示例,并确保它没有显示错误。
-
我会看看所需的输出,但我无法对 xml 本身做任何事情,因为这是我从 API 得到的?
-
“这是我从 API 中得到的”——不太可能;再次检查您的
r1。
标签: python pandas xml dataframe xpath