我有一个XML
文件,这个文件包含许多命名元素,每个元素下面有几个nodes
:
<name search = "select ARG: write">
<version id = "1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search = "select ARG: bla">
<version id = "2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
我想搜索这个XML
文件,如果这个名称搜索值以select ARG
开头(在我的例子中,这个第一个值是select ARG: write
)我想创建这个新的命名元素,但这次select ARG: write
的值应该是selected ARG: write
。这是我尝试过的:
from xml.dom import minidom
xamlfile = r'C:\file.xml'
newxamlfile = r'C:\new.xml'
dom = minidom.parse(xamlfile)
# Fetch the desired elements in the tree.
res = dom.getElementsByTagName('name')
# Loop through all.
for element in res:
search_name_value = element.getAttribute('search')
# Filter for the attribute and value.
if search_name_value.startswith('select ARG:'):
# In case of match, replace.
element.setAttribute('search_name', search_name_value.replace('select ARG:', 'selected ARG:'))
# Store the file.
with open(newxamlfile, 'w') as f:
f.write(dom.toxml())
在这里,我已经替换了所需的字符串而没有添加新的字符串,编辑我想要的元素而不是创建新的元素并将它们添加到文件中。
有什么建议怎么做?
UPDATE
这是我之前的文件:
<project version="4">
<name search="select ARG: write">
<version id="1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="select ARG: bla">
<version id="2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
</project>
这就是我想要的文件:
<project version="4">
<name search="select ARG: write">
<version id="1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="selected ARG: write">
<version id="1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="select ARG: bla">
<version id="2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="selected ARG: bla">
<version id="2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
</project>
编辑
根据@DirtyBit
的建议:
xmldoc = minidom.parse(xamlfile)
tags = xmldoc.getElementsByTagName("name")
for item in tags:
str = item.attributes["search"].value
if 'select ARG' in str:
item.attributes["search"].value = item.attributes["search"].value.replace('select ARG', 'selected ARG')
with open(xamlfile, "a+") as f:
xmldoc.writexml(f)
这工作正常,但我有两个问题:
select ARG
创建新节点(并将其替换为selected ARG
)而不是复制其他不符合此条件的节点。</element><?xml version="1.0" ?><element>
下面的代码克隆了所请求的元素,并将它们附加到文档的末尾。
55394530.xml是一个文件,其中包含从示例XML中获取的数据
import xml.etree.ElementTree as ET
import copy
from xml.dom import minidom
tree = ET.parse('55394530.xml')
names_to_duplicate = [e for e in tree.findall('.//name') if e.attrib.get('search').startswith('select ARG:')]
for name in names_to_duplicate:
clone = copy.deepcopy(name)
clone.attrib['search'] = clone.attrib['search'].replace('select', 'selected')
tree.getroot().append(clone)
xmlstr = minidom.parseString(ET.tostring(tree.getroot())).toprettyxml()
with open('out.xml', 'w') as out:
out.write(xmlstr)
产量
<element>
<name search="select ARG: 123">
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
</name>
<name search="select ARG: 456">
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
</name>
<name search="text ARG: 789">
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
</name>
<name search="foo ARG: 444">
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
</name>
<name search="test ARG: Cancel">
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
</name>
<name search="selected ARG: 123">
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
</name>
<name search="selected ARG: 456">
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
<version id="1.1.1">
<value>bla</value>
<method>blabla</method>
</version>
</name>
</element>
替换部分属性的解决方案(在使用新要求更新之前):
import xml.etree.ElementTree as ET
tree = ET.parse('example.xml')
for name in tree.getroot().iterfind('name'):
if name.attrib['search'].startswith('select ARG'):
name.attrib['search'] = name.attrib['search'].replace(
'select ARG', 'selected ARG')
tree.write('example.xml')
在上述解决方案中添加具有相同替换属性的新相同块的解决方案:
import xml.etree.ElementTree as ET
tree = ET.parse('example.xml')
for name in tree.getroot().iterfind('name'):
if name.attrib['search'].startswith('select ARG'):
new = ET.Element(name.tag)
new.attrib['search'] = name.attrib['search'].replace(
'select ARG', 'selected ARG')
tree.getroot().append(new)
for version in name.iterfind('version'):
new.append(version)
tree.write('example.xml')
解析(source,parser = None) 将外部XML部分加载到此元素树中。 source是文件名或文件对象。 parser是一个可选的解析器实例。如果没有给出,则使用标准XMLParser解析器。返回节根元素。
getroot() 返回此树的根元素。
iterfind(匹配) 按标签名称或路径查找所有匹配的子元素。与getroot()。iterfind(匹配)相同。返回一个iterable,以文档顺序生成所有匹配元素。
ATTRIB 包含元素属性的字典。请注意,虽然attrib值始终是一个真正的可变Python字典,但ElementTree实现可能会选择使用另一个内部表示,并且只有在有人要求时才创建字典。要利用此类实现,请尽可能使用下面的字典方法。
class xml.etree.ElementTree.Element(tag,attrib = {},** extra) 元素类。此类定义Element接口,并提供此接口的参考实现。
元素名称,属性名称和属性值可以是字节字符串或Unicode字符串。 tag是元素名称。 attrib是一个可选字典,包含元素属性。 extra包含作为关键字参数给出的其他属性。
追加(子元素) 将元素子元素添加到此元素内部子元素列表的末尾
write(file,encoding =“us-ascii”,xml_declaration = None,default_namespace = None,method =“xml”) 将元素树作为XML写入文件。 file是文件名,或者是为写入而打开的文件对象。 encoding [1]是输出编码(默认为US-ASCII)。 xml_declaration控制是否应将XML声明添加到文件中。永远使用False,始终使用True,仅当不是US-ASCII或UTF-8时使用None(默认为None)。 default_namespace设置默认的XML命名空间(对于“xmlns”)。 method是“xml”,“html”或“text”(默认为“xml”)。返回编码的字符串。
使用minidom,一旦你有了新的元素,在附加模式a+
中打开文件并写入:
list.txt(之前):
<project version="4">
<name search="select ARG: write">
<version id="1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="select ARG: bla">
<version id="2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
</project>
因此:
from xml.dom import minidom
xmldoc = minidom.parse('list_test.xml')
tags = xmldoc.getElementsByTagName("name")
for item in tags:
item.attributes["search"].value = item.attributes["search"].value.replace(
'select ARG', 'selected ARG')
with open("list_test.xml", "a+") as f:
xmldoc.writexml(f)
list.txt(之后):
<project version="4">
<name search="select ARG: write">
<version id="1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="select ARG: bla">
<version id="2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
</project><?xml version="1.0" ?>
<project version="4">
<name search="selected ARG: write">
<version id="1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="selected ARG: bla">
<version id="2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
</project>
如果你可以使用lxml,这是一个使用XPath谓词来检查search
属性值的解决方案。
选择正确的name
元素后,它会复制并更新属性值。
然后它在原始的name
元素之后添加新的name
元素。
XML输入(input.xml)
<project version="4">
<name search="select ARG: write">
<version id="1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="select ARG: bla">
<version id="2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
</project>
蟒蛇
from lxml import etree
from copy import deepcopy
tree = etree.parse("input.xml")
for name in tree.xpath("//name[starts-with(@search,'select ARG')]"):
new_name = deepcopy(name)
new_name.attrib["search"] = name.get("search").replace("select ARG", "selected ARG")
name.addnext(new_name)
tree.write("output.xml")
XML输出(带有轻微格式更改的output.xml以提高可读性)
<project version="4">
<name search="select ARG: write">
<version id="1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="selected ARG: write">
<version id="1.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="select ARG: bla">
<version id="2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
<name search="selected ARG: bla">
<version id="2.0.0">
<value>myVal</value>
<method>myMethod</method>
</version>
</name>
</project>