从python中的for循环添加到原始xml文件

时间:2013-08-26 17:07:34

标签: python xml elementtree minidom

我有一个名为vs_origonal_M.xml的主xml文件我想添加某个孩子的所有类型

<location>  
</location>
<location>
</location>
.
.
.
<location>
</location>

直到查看完所有文件。

我这样做是先打开目录,然后我正在制作目录中所有文件的列表,并检查它们是否确实是xml文件,然后我将某个孩子带出去。然后(这里是我被困的地方)我需要打开主文件并将这个孩子插入到同名的最后一个子项下,最后当我完成所有我需要保存主xml文件

以下是代码:

# List the xml files in the directory
from xml.dom import minidom
from xml.etree import ElementTree as ET
import glob
import os
import sys


def is_xml(HART_filename):
 string_length = len(HART_filename)
 suffix = '.xml'
 if HART_filename.endswith(suffix):
    return True 
 else:
    return False 

#add the directory to the python script
os.chdir("c:/Users/ME/Documents/XML_Parasing_Python")

#List all the files in an array
xml_list = os.listdir("c:/Users/ME/Documents/XML_Parasing_Python")
print xml_list
xml_list_length = len(xml_list)
print xml_list_length
number = 1

for number in range(1,xml_list_length):
    string_length = len(xml_list[number])
    #print string_length
    print xml_list[number]
    #check to see if file is .xml
    if is_xml(xml_list[number]) == True: 
        xmldoc = minidom.parse(xml_list[number])
        reflist = xmldoc.getElementsByTagName('location')
        var_ref = reflist[0]
        print reflist[0].toxml()
        #Add to master .xml file
        tree = ET.parse('vs_original_M.xml')
        number += 1
    else:
        number += 1
        print 'wasn''t true'

1 个答案:

答案 0 :(得分:1)

可能有更好的方法来做你真正想做的事情 - 特别是,真正的XML很可能只有一个<locations>标签,所有<location>标签都在下面,所以有没理由完全搜索最后一个<location>标签...

但这是你怎么做的。

os.chdir('c:/Users/ME/Documents/XML_Parasing_Python/')
origname = 'vs_original_M.xml'
master = ET.parse(origname)
for path in os.listdir('.'):
    if path != origname and os.path.splitext(path)[-1] == '.xml':
        child = ET.parse(path)
        root = child.getroot()
        last_location_parent = master.find('.//*[{}][last()]'.format(root.tag))
        last_location_parent.append(root)
master.write('master.xml')

大部分内容非常简单。您必须找到最后一个location节点的父节点,然后您可以append另一个节点。

唯一棘手的问题是find中的XPath表达式,所以让我为你分解它(但你必须阅读文档才能真正理解它!):

  • .//表示“当前节点的后代”。 (从技术上讲,你应该只能使用//作为“root的后代”,但是早期版本的etree中存在错误,所以这样更安全。)
  • *表示“带有任何标记名称”。
  • [location]表示“带有孩子”位置“标记。(当然我正在使用format方法填写孩子的根标签。如果您知道所有孩子都有{{ 1}}作为根,您可以对标记名称进行硬编码,并将location移出循环。)
  • find表示“最后一个”。

所以,把它们放在一起,这是根的最后一个后代,任何带有子“location”标记的名称。


如果您不了解XPath,您可以随时手动迭代以获得相同的效果,但它会更长,更容易引入细微的错误,因此非常值得学习XPath。


我在你的程序中改变了很多其他的东西。让我解释一下:

没有理由[last()] if foo: return True;你可以做else: return False。但这意味着你的整个函数只是return foo,所以你甚至不需要一个函数。最好使用路径函数,如return HART_filename.endswith('.xml'),而不是路径上的字符串函数。

如果您执行os.path.splitext,则开始时不需要for number in range(1, xml_list_length),循环中不需要number = 1; number += 1语句已经为您做了。

但是你不想从1开始; Python列表从0开始编制索引。如果您使用它来跳过for,那只有在您运气好的情况下才有效; vs_original_M.xml返回内容的顺序是未指定且任意的。跳过具有特定名称的文件的唯一方法是检查其名称。

你几乎不想循环listdir。如果您只需要range(len(foo))的元素,请执行foo。如果您还需要每个元素的索引,请执行for element in foo

最后,你几乎不应该检查for index, element in enumerate(foo)。在Python中,除了if foo == True(数字True,字符串“hello”等)之外,很多东西都是“真实的”,你可以使用74检查foo是否是truthy。如果您明确要确保其失败或其他真实值,请仅使用if foo;如果您只想检查布局函数的结果,如== Trueis_xmlendswith运算符,请直接检查。