Поиск и замена элементов в XML-файле с использованием Python - PullRequest
0 голосов
/ 20 февраля 2019

Мне нужно найти элемент и заменить его другим значением в файле 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.text это sk-log и vn.text это 1.7.25.Мне нужно заменить 1.7.25 на 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>

Ответы [ 3 ]

0 голосов
/ 20 февраля 2019

Использование BeautifulSoup и find_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>
0 голосов
/ 20 февраля 2019

Вот что вам нужно: импортировать 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')   
0 голосов
/ 20 февраля 2019

вы пытаетесь изменить этот xml, чтобы диктовать его модулем xmltodict, а затем снова изменить его на 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))

С уважением

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...