使用python搜索和替换XMLfile中的元素

时间:2019-02-20 07:39:17

标签: python xml search replace

我需要搜索element并用XML文件中的另一个值替换。替换只能在条件匹配的行发生。

我有以下xml文件。

/sbin/ip route|awk '/default/ { print $3 }'

下面是替换代码。

<?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.textsk-logvn.text。我只需要在该特定行中将1.7.25替换为1.7.25。上面的代码对我不起作用。我该怎么办?

预期输出为

somevalue

3 个答案:

答案 0 :(得分:0)

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

Here is a little guide

And here the repository

这是一个小功能,可以替换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

我制作了这个程序,并在perf上工作:

# -*- 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))

致谢

答案 1 :(得分:0)

使用BeautifulSoupfind_next()

list_text.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>

然后:

from bs4 import BeautifulSoup
with open('list_test.xml','r') as f:
    soup = BeautifulSoup(f.read(), "html.parser")
    aid = soup.find_all('aid')
    for s in aid:
        if s.text == 'sk-log':
            vn = s.find_next('vn')
            print("Original Value: {}".format(vn.text))
            vn.string = 'SomeValue'
            print("Replaced value: {}".format(vn.text))

输出:

Original Value: 1.7.25
Replaced value: SomeValue

编辑:

要将其写入相同的xml文件,我们将使用soup.prettify()

from bs4 import BeautifulSoup
with open('list_test.xml','r') as f:
    soup = BeautifulSoup(f.read(), features="lxml")
    aid = soup.find_all('aid')
    for s in aid:
        if s.text == 'sk-log':
            vn = s.find_next('vn')
            print("Original Value: {}".format(vn.text))
            vn.string = 'SomeValue'
            print("Replaced value: {}".format(vn.text))

with open("list_test.xml", "w") as f_write:
    f_write.write(soup.prettify())

输出:

<?xml vn="1.0" encoding="UTF-8"?>
<html>
 <body>
  <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>
 </body>
</html>

答案 2 :(得分:0)

这是您需要的:     导入xml.etree.ElementTree作为ET

tree = ET.parse('test.xml')  
root = tree.getroot()
aIdValue = "sk-log"

for elt in root.iter("dp"):
  print("%s - %s" % (elt.tag, elt.text))
  aId = elt.find("aId")
  vn = elt.find("vn")
  print(aId.text)
  print(vn.text)
  if (aId.text == aIdValue):
    print("vn will be changed.")
    elt.find("vn").text='1.8.0'

tree.write('test.xml', 'unicode')