Python:如何编辑XML文件的元素?

fal*_*kky 5 python xml

我有一个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>
Run Code Online (Sandbox Code Playgroud)

我想搜索这个XML文件,如果这个名称搜索值以select ARG(在我的示例中第一个值是select ARG: write)开头,我想创建这个新的命名元素,但这次的值应该select ARG: writeselected 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())
Run Code Online (Sandbox Code Playgroud)

在这里,我替换了所需的字符串,但没有添加新的字符串,而是编辑所需的元素,而不是创建新的元素并将它们添加到文件中。

有什么建议如何做到这一点吗?

更新

这是我之前的文件:

<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>
Run Code Online (Sandbox Code Playgroud)

这就是我希望我的文件的样子:

<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>
Run Code Online (Sandbox Code Playgroud)

编辑

根据@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)
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我有两个问题:

  1. 正如您所看到的,我添加了 if 语句,因为我只想在值为 with 时复制并创建新节点select ARG(并将其替换为selected ARG),而不复制不符合此条件的其他节点。

  2. 在新 XML 文件的中间有这样一行:

    </element><?xml version="1.0" ?><element>

ear*_*arw 3

替换部分属性的解决方案(在用新要求更新之前):

\n\n
import xml.etree.ElementTree as ET\n\ntree = ET.parse(\'example.xml\')\n\nfor name in tree.getroot().iterfind(\'name\'):\n    if name.attrib[\'search\'].startswith(\'select ARG\'):\n        name.attrib[\'search\'] = name.attrib[\'search\'].replace(\n            \'select ARG\', \'selected ARG\')\n\ntree.write(\'example.xml\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用与上述解决方案相同的属性替换来附加新的相同块的解决方案:

\n\n
import xml.etree.ElementTree as ET\n\ntree = ET.parse(\'example.xml\')\n\nfor name in tree.getroot().iterfind(\'name\'):\n    if name.attrib[\'search\'].startswith(\'select ARG\'):\n        new = ET.Element(name.tag)\n        new.attrib[\'search\'] = name.attrib[\'search\'].replace(\n            \'select ARG\', \'selected ARG\')\n        tree.getroot().append(new)\n        for version in name.iterfind(\'version\'):\n            new.append(version)\n\ntree.write(\'example.xml\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

来自ElementTree 文档

\n\n
\n

parse(source, parser=None)
将外部 XML 部分加载到此元素树中。source 是文件名或文件对象。解析器是一个可选的解析器实例。如果未给出,则使用标准 XMLParser 解析器。返回节根元素。

\n\n

getroot()
返回此树的根元素。

\n\n

iterfind(match)
按标签名称或路径查找所有匹配的子元素。与 getroot().iterfind(match) 相同。返回一个可迭代的,产生\n 按文档顺序匹配的所有元素。

\n\n

attrib
包含 element\xe2\x80\x99s 属性的字典。请注意,虽然 attrib 值始终是一个真正的可变 Python 字典,\n ElementTree 实现可以选择使用另一个内部\n 表示形式,并且仅在有人要求时才创建字典。\n 要利用此类实现,请使用尽可能使用下面的字典方法。

\n\n

class xml.etree.ElementTree.Element(tag, attrib={}, **extra)
元素类。此类定义 Element 接口,并提供\n此接口的参考实现。

\n\n

元素名称、属性名称和属性值可以是字节字符串或 Unicode 字符串。tag 是元素名称。attrib 是一个可选字典,包含元素属性。extra 包含附加属性,以关键字参数形式给出。

\n\n

append(subelement)
\n 将元素子元素添加到该元素内部子元素列表的末尾

\n\n

write(file,encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml")
将元素树以 XML 形式写入\n 文件。file 是文件名或为写入而打开的文件对象。编码 [1] 是输出编码(默认为 US-ASCII)。\n xml_declaration 控制是否应将 XML 声明添加到\n 文件中。使用 False 表示从不,True 表示始终,None 表示仅在不使用时\n US-ASCII 或 UTF-8(默认值为 None)。default_namespace 设置默认 XML 命名空间(对于 \xe2\x80\x9cxmlns\xe2\x80\x9d)。方法是“xml”、“html”或\n“text”(默认为“xml”)。返回编码的字符串。

\n
\n