【问题标题】:How to replace an XML node via python如何通过 python 替换 XML 节点
【发布时间】:2020-08-10 08:27:07
【问题描述】:

我是 python 新手,我对 XML 文件有一个 - 可能 - 愚蠢的问题(是的,我试图用谷歌搜索解决方案,但没有结果)。

我必须编写一个程序来替换/切换两件事,所以首先,这里是 XML 数据,它看起来像这样:

<data='qwerty'>
    <name_it>some_name</name_it>
</data>

<next_data='next_qwerty'>
    <name_it>another_name</name_it>
</next_data>

<next_next_data>
...
</next_next_data>
<next_xyz_data>...
etc.

如何在 python 中将some_name 更改为data=''? 所以应该是这样的:

<data='some_name'>                            #changed from 'qwerty' to some_name
    <name_it>some_name</name_it>
</data>

<next_data='another_name'>                    #changed from 'next_qwerty' to another_name
    <name_it>another_name</name_it>
</next_data>

如果这是一个愚蠢的问题,很抱歉,但我确实在谷歌上搜索过,但找不到解决方案。

更新: 这是我写的几行python代码:

from xml_file import data

new=""

f = io.StringIO(data)  # data loading
for r in f: 
    row = r.rstrip() 
    if 'name_it' in row: 
        change = row[row.index('name_it')] # maybe kind of len() or something
    if "<data>" in row and change: 
        idx = row.index("<data>") + 6
        new += row[:idx] + change + "name_it=\n"
        change = ""  
    else:
        new += row + "\n" # new line

这是真正的 XML 数据:

<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="Setup">
    <testcase classname="Configuration" name="xxx">
        <data>abc_qwe</data>                       #change_me_to_"xxx"
    </testcase>
    <testcase classname="Configuration" name="yyy">
        <data>xyzzzz</data>                        #change_me_to_"yyy"
    </testcase>
</testsuite>

有很多迹象。 只需&lt;data&gt;...&lt;/data&gt; 名称应在name="..."

好的,这里是文件的内容。 首先,我正在生成 CSV 文件:

Type,Name,Request Count,Failure Count,Median Response Time,Average Response Time,Min Response Time,Max Response Time,Average Content Size,Requests/s,Failures/s,50%,66%,75%,80%,90%,95%,98%,99%,99.9%,99.99%,99.999%,100%
POST,---ON START---LOGIN,33,0,2023.709774017334,2037.008133801547,2023.709774017334,2058.631658554077,6587.515151515152,0.24352046353820625,0.0,2000,2000,2000,2000,2100,2100,2100,2100,2100,2100,2100,2100
GET,Aggregations,15,0,4,5.305735270182292,3.652334213256836,11.571884155273438,6174.2,0.11069111979009376,0.0,4,5,7,7,9,12,12,12,12,12,12,12
GET,Alarms,5,0,5,4.584074020385742,3.754138946533203,5.759000778198242,6173.8,0.03689703993003125,0.0,5,5,5,6,6,6,6,6,6,6,6,6
GET,Analysis Templates,16,0,7,7.806003093719482,3.8690567016601562,13.520479202270508,6174.625,0.11807052777610001,0.0,9,11,11,11,12,14,14,14,14,14,14,14
GET,Boiler Efficiency,15,0,6,6.464735666910808,3.6771297454833984,15.489578247070312,6174.2,0.11069111979009376,0.0,6,6,8,11,11,15,15,15,15,15,15,15
GET,Configuration,14,0,5,6.087354251316616,3.6630630493164062,12.647390365600586,6174.428571428572,0.1033117118040875,0.0,5,6,8,11,11,13,13,13,13,13,13,13

然后,我想把它改成XML:

import _csv
from locust_script import methods_count
with open('locust_stats.csv') as f, open('locus_statistics.csv', 'w') as out:
    for line in f:
        if not line.isspace():
            print(line.strip())
            out.write(line)

stats = open('locus_statistics.csv')
csv_f = _csv.reader(stats)
data = []
for row in csv_f:
    data.append(row)

def convert_row(row, methods):
    case_name = methods[0]
    del methods[0]

    return """
            <testcase classname="test_perf" name="%s">
                <Type>%s</Type>
                <Name>%s</Name>
                <Request_Count>%s</Request_Count>
                <Failure_Count>%s</Failure_Count>
                <Median_Response_Time>%s</Median_Response_Time>
            </testcase>""" % (case_name, row[0], row[1], row[2], row[3], row[4])
report_save = open('parsed.xml', 'w')
case_name = methods_count()
report_save.write("<testsuite name='performance'>"+''.join([convert_row(row, case_name) for row in data[1:1000]])+"</testsuite>")
report_save.close()

最后,我想解析 XML,所以正如我上面写的,我尝试使用这种脚本:


from xml_file import data

new=""

f = io.StringIO(data)  # data loading
for r in f: 
    row = r.rstrip() 
    if 'name_it' in row: 
        change = row[row.index('name_it')] # maybe kind of len() or something
    if "<data>" in row and change: 
        idx = row.index("<data>") + 6
        new += row[:idx] + change + "name_it=\n"
        change = ""  
    else:
        new += row + "\n" # new line

所以我的意图就在这里 - 我认为 :) -:

            <testcase classname="test_perf" name="%s">
                <Type>%s</Type>
                <Name>%s</Name>

name="" 应该和&lt;Name&gt; HERE &lt;/Name&gt;一样

【问题讨论】:

  • 从分享开始 1) 一个有效的 xml 文档 2) 显示你到目前为止所做的 python 代码
  • 我认为 XML 结构不一定在这里。我已经用 python 代码更新了我的问题帖子。
  • 您可以使用 XML 解析来完成。如果您将分享一个有效的 XML 文档 - 我将能够指导您。
  • 给你,我已经写了几行junit报告:)

标签: python xml xml-parsing


【解决方案1】:

下面:

import xml.etree.ElementTree as ET

xml = '''<testsuite name="Setup">
    <testcase classname="Configuration" name="xxx">
        <data>abc_qwe</data>                      
    </testcase>
    <testcase classname="Configuration" name="yyy">
        <data>xyzzzz</data>                       
    </testcase>
</testsuite>'''


root = ET.fromstring(xml)
test_cases = root.findall('.//testcase')
for test_case in test_cases:
    test_case.find('./data').text = test_case.attrib['name']
    
ET.dump(root)

输出

<testsuite name="Setup">
    <testcase classname="Configuration" name="xxx">
        <data>xxx</data>                      
    </testcase>
    <testcase classname="Configuration" name="yyy">
        <data>yyy</data>                       
    </testcase>
</testsuite>

另一种方式(用数据的文本设置name属性的值)

import xml.etree.ElementTree as ET

xml = '''<testsuite name="Setup">
    <testcase classname="Configuration" name="xxx">
        <data>data_1</data>                      
    </testcase>
    <testcase classname="Configuration" name="yyy">
        <data>data_2</data>                       
    </testcase>
</testsuite>'''


root = ET.fromstring(xml)
test_cases = root.findall('.//testcase')
for test_case in test_cases:
    test_case.attrib['name'] = test_case.find('./data').text
    
ET.dump(root)

【讨论】:

  • 我明白了,但是如果我有 1000 个测试用例怎么办?也许对它们进行一些迭代?感谢您的解决方案。
  • 如您所见,代码不关心您是否有 2 个或 1000 个测试用例。如果我的解决方案有帮助 - 请随时投票。
  • 你当然是对的,但是new_values 列表中的这个迭代是怎么回事?如果我们有 1000 个值,我需要手动添加它们的名称,所以这里没有意义:/ 看看这个:new_values=[1,2,3,4,5,1231231,avasvas,qweeqw,123123526354,34342342...n]
  • 只有您(或您的软件的逻辑)才能说出替换值的逻辑。尝试解释替换的逻辑,也许有一个聪明的方法来做到这一点。
  • 又更新了一次。很抱歉造成混乱
猜你喜欢
  • 2012-01-04
  • 2014-08-27
  • 1970-01-01
  • 2013-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-05
  • 2013-07-11
相关资源
最近更新 更多