元素树以不同方式处理类似文件

时间:2013-06-20 23:35:36

标签: python parsing element

这是我的python(2.6)脚本遇到的两个不同的文件。一个人会解析,另一个则不会。我只是好奇为什么会这样。

此xml文件不会解析,脚本将失败:

<Landfire_Feedback_Point_xlsform id="fbfm40v10" instanceID="uuid:9e062da6-b97b-4d40-b354-6eadf18a98ab" submissionDate="2013-04-30T23:03:32.881Z" isComplete="true" markedAsCompleteDate="2013-04-30T23:03:32.881Z" xmlns="http://opendatakit.org/submissions">
<date_test>2013-04-17</date_test>
<plot_number>10</plot_number>
<select_multiple_names>BillyBob</select_multiple_names>
<geopoint_plot>43.2452830500 -118.2149402900 210.3000030518 3.0000000000</geopoint_plot><fbfm40_new>GS2</fbfm40_new>
<select_grazing>NONE</select_grazing>
<image_close>1366230030355.jpg</image_close>
<plot_note>No road present.</plot_note>
<n0:meta xmlns:n0="http://openrosa.org/xforms">
<n0:instanceID>uuid:9e062da6-b97b-4d40-b354-6eadf18a98ab</n0:instanceID>
</n0:meta>
</Landfire_Feedback_Point_xlsform>

此xml文件将正确解析并且脚本成功:

<Landfire_Feedback_Point_xlsform id="fbfm40v10">
<date_test>2013-05-14</date_test>
<plot_number>010</plot_number>
<select_multiple_names>BillyBob</select_multiple_names>
<geopoint_plot>43.26630563 -118.39881809 351.70001220703125 5.0</geopoint_plot>
<fbfm40_new>GR1</fbfm40_new>
<select_grazing>HIGH</select_grazing>
<image_close>fbfm40v10_PLOT_010_ID_6.jpg</image_close>
<plot_note>Heavy grazing</plot_note>
<meta><instanceID>uuid:90e7d603-86c0-46fc-808f-ea0baabdc082</instanceID></meta>
</Landfire_Feedback_Point_xlsform>

这是一个小的python脚本,它表明一个可以工作,而另一个不会。我只是在寻找一个解释,为什么ElementTree将其视为xml文件,而另一个则不是。具体来说,似乎没有解析的那个失败的是“'NONE'类型没有'text'属性”或类似的东西。但是,这是因为它似乎没有将文件视为xml,或者它看不到开头行之外的任何元素。任何有关此错误的解释或指示都将不胜感激。提前谢谢。

Python脚本:

import os
from xml.etree import ElementTree


def replace_xml_attribute_in_file(original_file,element_name,attribute_value):
    #THIS FUNCTION ONLY WORKS ON XML FILES WITH UNIQUE ELEMENT NAMES
    #  -DUPLICATE ELEMENT NAMES WILL ONLY GET THE FIRST ELEMENT WITH A GIVEN NAME

    #split original filename and add tempfile name
    tempfilename="temp.xml"
    rootsplit = original_file.rsplit('\\')  #split the root directory on the backslash
    rootjoin = '\\'.join(rootsplit[:-1]) #rejoin the root diretory parts with a backslash -minus the last 
    temp_file = os.path.join(rootjoin,tempfilename) 
    et = ElementTree.parse(original_file)
    author=et.find(element_name)
    author.text = attribute_value
    et.write(temp_file)
    if os.path.exists(temp_file) and os.path.exists(original_file): #if both the original and the temp files exist
        os.remove(original_file)                                    #erase the original
        os.rename(temp_file,original_file)                          #rename the new file
    else:
        print "Something went wrong."

replace_xml_attribute_in_file("testfile1.xml","image_close","whoopdeedoo.jpg");

1 个答案:

答案 0 :(得分:0)

  

这是一个小的python脚本,它表明一个可以工作,而另一个不会。我只是在寻找一个解释,为什么ElementTree会将其视为xml文件,而另一个则不是。

您的代码根本没有证明。它表明它们被ElementTree视为有效的XML文件,充满了节点。他们都解析得很好,他们都读过第一行等等。

唯一的问题是第一个没有名为'image_close'的节点,所以你的代码不起作用。

你可以很容易地看到:

for node in et.getroot().getchildren():
    print node.tag

您可以获得9个root用户,其中包含任何一个版本。

输出到那应该会告诉你问题。您想要的节点实际上在第一个示例中命名为{http://opendatakit.org/submissions}image_close,而不是在第二个示例中命名为image_close

而且,正如您可能猜到的那样,这是因为根节点中的namespace=http://opendatakit.org/submissions。 ElementTree使用"James Clark notation"将未知名称空间的名称映射到通用名称。

无论如何,因为没有一个节点被命名为image_close,所以et.find(element_name)返回None,因此您的代码存储author=None,然后尝试分配给author.text },并收到错误。

至于如何解决这个问题......好吧,您可以在ElementTree中了解命名空间如何工作,或者您可以升级到Python 2.7或安装更新的ElementTree for 2.6,它可以让您更轻松地自定义事物。但是,如果你想进行自定义命名空间处理并坚持使用旧版本......我将从this article(及其两个前身)和this one开始。