首页 > 解决方案 > 使用python搜索和替换XMLfile中的元素

问题描述

我需要在 XML 文件中搜索元素并替换为另一个值。替换应该只发生在条件匹配的行上。

我有以下 xml 文件。

<?xml vn="1.0" encoding="UTF-8"?>
<proj>
    <mV>4.0.0</mV>

    <gId>com.test</gId>
    <aId>console</aId>
    <vn>1.0</vn>

    <bld>
        <plugins>
            <plugin>
                <gId>org.apache.maven.plugins</gId>
                <aId>maven-compiler-plugin</aId>
                <vn>1.1</vn>
                <configuration>
                    <source>1.0</source>
                    <target>1.0</target>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
        </plugins>
    </bld>
    <dps>
        <dp>
            <gId>org.sk</gId>
            <aId>sk-api</aId>
            <vn>1.7.20</vn>
        </dp>
        <dp>
            <gId>org.sk</gId>
            <aId>sk-log</aId>
            <vn>1.7.25</vn>
        </dp>
    </dps>
</proj>

下面是替换代码。

aIdValue = "sk-log"
tree = ET.parse('test.xml')
al_rt = tree.getal_rt()
dp = al_rt.findall(".//xmlns:dp")
for d in dp:
    aId = d.find("xmlns:aId")
    vn    = d.find("xmlns:vn")
    if aIdValue == aId.text:
       print aId.text
        print vn.text
        vn.text = vn.text
        tree.write('test.xml')

所以在这里我从打印语句中获取值aId.textissk-logvn.textis 1.7.25。我只需要在该特定行1.7.25中用on 替换。somevalue上面的代码对我不起作用。我怎样才能做到这一点?

预期的输出将是

<?xml vn="1.0" encoding="UTF-8"?>
<proj>
    <mV>4.0.0</mV>

    <gId>com.test</gId>
    <aId>console</aId>
    <vn>1.0</vn>

    <bld>
        <plugins>
            <plugin>
                <gId>org.apache.maven.plugins</gId>
                <aId>maven-compiler-plugin</aId>
                <vn>1.1</vn>
                <configuration>
                    <source>1.0</source>
                    <target>1.0</target>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
        </plugins>
    </bld>
    <dps>
        <dp>
            <gId>org.sk</gId>
            <aId>sk-api</aId>
            <vn>1.7.20</vn>
        </dp>
        <dp>
            <gId>org.sk</gId>
            <aId>sk-log</aId>
            <vn>somevalue</vn>
        </dp>
    </dps>
</proj>

标签: pythonxmlsearchreplace

解决方案


您是否尝试使用模块 xmltodict 将该 xml 更改为 dict,然后再次将其更改为 xml?

这是一个小指南

这里是存储库

这是一个替换dict上元素的小功能,当两个键相等时会出现问题,但是对于用不重复的键替换元素没关系,至少对我有用:

def changes_dict(self, tree, change):
    """Function that changes the values of a json with the keys given
    :param tree: Json to be changed
    :param change: Dictionary with the keys to be changed and the new values: {field1: value1, field2: value2,..., fieldN: valueN}"""
    if isinstance(tree,(list,tuple)):
        res = []
        for subItem in tree:
            result = self.changes_dict(subItem, change)
            res.append(result)
        return res
    elif isinstance(tree,dict):
        for nodeName in tree.keys():
            subTree = tree[nodeName]
            if nodeName in list(change.keys()):
                tree[nodeName] = {'value': str(change[nodeName])}
                change.pop(nodeName)
                if not change:
                    break
            else:
                tree[nodeName] = self.changes_dict(subTree, change)
        return tree
    elif isinstance(tree, str):
        return tree

我制作了这个程序并且性能很好:

# -*- coding: utf-8 -*-

import xmltodict, json

def changes_dict(tree, change, wordHelp):
    """Function that changes the values of a json with the keys given
    :param tree: Json to be changed
    :param change: Dictionary with the keys to be changed and the new values: {field1: value1, field2: value2,..., fieldN: valueN}
    :param wordHelp: Word that must be in the values of the dict that contains the change"""
    if isinstance(tree,(list,tuple)):
        res = []
        for subItem in tree:
            result = changes_dict(subItem, change, wordHelp)
            res.append(result)
        return res
    elif isinstance(tree,dict):
        for nodeName in tree.keys():
            subTree = tree[nodeName]
            if nodeName in list(change.keys()) and wordHelp in list(tree.values()):
                tree[nodeName] = {'value': str(change[nodeName])}
                change.pop(nodeName)
                if not change:
                    break
            else:
                tree[nodeName] = changes_dict(subTree, change, wordHelp)
        return tree
    elif isinstance(tree, str):
        return tree

 x = """
 <proj>
    <mV>4.0.0</mV>

        <gId>com.test</gId>
        <aId>console</aId>
        <vn>1.0</vn>

        <bld>
            <plugins>
                <plugin>
                    <gId>org.apache.maven.plugins</gId>
                    <aId>maven-compiler-plugin</aId>
                    <vn>1.1</vn>
                    <configuration>
                        <source>1.0</source>
                        <target>1.0</target>
                        <showWarnings>true</showWarnings>
                    </configuration>
                 </plugin>
             </plugins>
         </bld>
         <dp>
            <gId>org.sk</gId>
            <aId>sk-api</aId>
            <vn>1.7.20</vn>
        </dp>
        <dp>
            <gId>org.sk</gId>
            <aId>sk-log</aId>
            <vn>1.7.25</vn>
        </dp>
    </dps>
</proj> """

dicti = eval(json.dumps(xmltodict.parse(x)))
dicti_changed = changes_dict(dicti, {'vn': 'somevalue'}, 'sk-log')
print(xmltodict.unparse(dicti_changed))

问候


推荐阅读