从xml中获取值

2024-10-02 08:27:16 发布

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

我需要先说我对编写代码完全陌生。我一直在尝试从xml文件中获取信息,但可能添加了失败的信息。xml文件中的一个小片段如下所示:

<?xml version="1.0"?>
<AlertRequestType xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <DateTime xmlns="http://EU/Common/20181/">2021-06-15T08:55:08.441</DateTime>
  <Code xmlns=>A68</Code>
  <UniqueAlertId xmlns="http://EU/20181/">US-8I2-NVH-7JH-0A1- 
   54M</UniqueAlertId>
  <Message xmlns="http://EU/Common/20181/">B-Id mismatch.</Message>
  <Source xmlns="http://EU/2556781/">National S I</Source>
  <SupportingData xmlns="http://EMVS.EU/Common/20181/">
    <Item key="errorcode" value="A68" />
    <Item key="errormessage" value="B-Id mismatch." />
    <Item key="date" value="2021-06-15" />
    <Item key="time" value="21:35:03" />
    <Item key="uniquealertid" value="US-8I2-NVH-7JH-0A1-54M" />
    <Item key="productcode" value="988356696047773" />
    <Item key="serialnumber" value="PFL72KBN85S22" />
    <Item key="b-id" value="QD88223402+G+1332" />
   </SupportingData>
</AlertRequestType>

现在,我的问题是,作为一个对ElementTree和总体编码理解非常差的人: 如何从特定的“<;Item key=”中获取值?例如,从值为A68的item key errorcode。 真正重要的是,所有的值都会改变,因为我每天都会使用这些值处理不同的文件(项目键属性,如date或errorcode,永远不会改变,只会改变它们的值),所以我不能只编写代码来搜索一个特定的值,每次都需要从这个xpath中获取值

下面是我试图修改的代码,以满足我的需要,但可惜没有成功

import xml.etree.ElementTree as ET                                                        
import os                                                                                 
                                                                                          
xmlfile = 'xmltest.xml'                                                              
fullfile = os.path.abspath(os.path.join('filer', xmlfile))                                
                                                                                          
tree = ET.parse(fullfile)                                                                 
root = tree.getroot()                                                                     
ET.dump(tree)                                                                             
                                                                                          
for elm in root.findall("./SupportingData/Item key/errorcode[@value=]"):                  
    print(elm.attrib)                                                                     

同样,这段代码来自于一个对编码完全陌生的人。 如果有人能帮我,我会永远感激的


Tags: 文件key代码httpvalueosxmlcommon
2条回答

首先,我们需要修复作为示例提供的XML:

<?xml version="1.0"?>
<AlertRequestType xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <DateTime xmlns="http://EU/Common/20181/">2021-06-15T08:55:08.441</DateTime>
  <Code xmlns="">A68</Code> <!  Closing xmlns attribute  >
  <UniqueAlertId xmlns="http://EU/20181/">US-8I2-NVH-7JH-0A1- 
   54M</UniqueAlertId>
  <Message xmlns="http://EU/Common/20181/">B-Id mismatch.</Message>
  <Source xmlns="http://EU/2556781/">National S I</Source>
  <SupportingData xmlns="http://EMVS.EU/Common/20181/">
    <Item key="errorcode" value="A68" />
    <Item key="errormessage" value="B-Id mismatch." />
    <Item key="date" value="2021-06-15" />
    <Item key="time" value="21:35:03" />
    <Item key="uniquealertid" value="US-8I2-NVH-7JH-0A1-54M" />
    <Item key="productcode" value="988356696047773" />
    <Item key="serialnumber" value="PFL72KBN85S22" />
    <Item key="b-id" value="QD88223402+G+1332" />
   </SupportingData>
</AlertRequestType>

其次,我建议您使用更简单的库,下面的代码正是您想要的:

import os
import xml.dom.minidom                                                                     
                                                                                      
if __name__ == "__main__":
    xmlfile = 'xmltest.xml'                                                              
    fullfile = os.path.abspath(os.path.join('filer', xmlfile))      
    doc = xml.dom.minidom.parse(fullfile)
    items = doc.getElementsByTagName("Item")
    for i in items:
        print("Key:" + i.getAttribute("key"))
        print("Value:" + i.getAttribute("value"))

输出为:

Key:errorcode
Value:A68
Key:errormessage
Value:B-Id mismatch.
Key:date
Value:2021-06-15
Key:time
Value:21:35:03
Key:uniquealertid
Value:US-8I2-NVH-7JH-0A1-54M
Key:productcode
Value:988356696047773
Key:serialnumber
Value:PFL72KBN85S22
Key:b-id
Value:QD88223402+G+1332

我已经针对您的问题给出了解决方案,但我建议您创建一个名为XMLReader的类,并在其中添加您想要的所有XML操作

您问题中的XML不可能被解析——我假设与@Bruno显示的XML相同。下次在这里发布问题时,请确保问题中的数据(和代码)有效

Minidom可能是解决眼前问题的一种方法,但一般来说,我认为ElementTree具有更好的xml支持,尽管如果您需要更复杂的xpath,那么lxml或其他库会更好

无论如何,要解决您的特定问题,xpath不起作用的第一个原因是因为xml使用名称空间

特别是对于xml,这一行指定下面的标记位于命名空间http://EMVS.EU/Common/20181/

<SupportingData xmlns="http://EMVS.EU/Common/20181/">

xpath无法工作的第二个原因是Item key/errorcode[@value=]的xpath语法不正确-这应该是Item[@key='errorcode'],但名称空间问题意味着您尚未达到匹配失败或可能导致异常的程度

因此,xpath需要在{}中包含用于标记的名称空间,否则它将不匹配。这项工作:

for elm in root.findall("./{http://EMVS.EU/Common/20181/}SupportingData/{http://EMVS.EU/Common/20181/}Item[@key='errorcode']"):
    print(elm)
    print(elm.attrib)

使用名称空间时,很难使xpath字符串正常工作。当您开始尝试匹配一长串标记/属性时,您不知道哪一位不匹配。我的方法非常简单:从匹配第一个xpath部分开始,即:

for elm in root.findall("./{http://EMVS.EU/Common/20181/}SupportingData"):

检查是否有效-在第一个xpath有效之前,没有必要添加更多内容,然后添加下一个匹配项,检查是否有效,添加下一个匹配项,等等。这样,当xpath不匹配时,就是您刚才添加的部分,这就是问题所在

还有其他匹配名称空间的方法,例如提供名称空间字典并使用类似findall('role:character', ns)的名称空间-ElementTree文档中有一些示例https://python.readthedocs.io/en/stable/library/xml.etree.elementtree.html

如果您不打算写出XML,并且在多个名称空间中没有使用标记,那么另一种非常方便的方法是简单地将所有名称空间从标记中剥离,也可能从属性中剥离。请参见@nonagon和我在这里的例子Python ElementTree module: How to ignore the namespace of XML files to locate matching element when using the method "find", "findall"

相关问题 更多 >

    热门问题