【问题标题】:How to order Xml file according to CSV ordering using python?如何使用 python 根据 CSV 排序来排序 Xml 文件?
【发布时间】:2021-09-18 15:38:05
【问题描述】:

我有一个 CSV 文件:-

   TestName
0    Test5
1    Test1
3    Test6

xml 文件包含测试用例名称及其详细信息。这只是一个示例,但我在 xml 文件中有数千个这样的测试用例。

我有一个 CSV 文件,它也包含相同的测试用例,但按顺序排列。顺序是使用一些特定参数定义的,例如最短处理时间优先。

我有这个 XML 文件:- final.xml

<?xml version="1.0"?>
<TestSuite Name="DM123">
  <Group Name="TestRoot" ExecutionPolicy="AnyDeviceAnyOrder">
    <Parameters>
      <Parameter Type="Integer" Name="maxA" Value="1" />
      <Parameter Type="Integer" Name="MaxB" Value="120" />
      <Parameter Type="String" Name="MaxC" Value="integration" />
    </Parameters>
    <Children>
      <Test Name="Test1" Namespace="TestCases">
        <Parameters>
           <Parameter Type="Device" Name="Device">
             <Requirements>
               <Requirement TypeId="a76" Source="User" />
               <Requirement TypeId="2c9" Source="User" />
             </Requirements>
           </Parameter>
        </Parameters>
      </Test>
      <Test Name="Test5" Namespace="TestCases">
        <Parameters>
           <Parameter Type="Dev" Name="Dev">
               <Requirements>
                 <Requirement TypeId="a76" Source="User" />
                 <Requirement TypeId="2c9" Source="User" />
               </Requirements>
           </Parameter>
        </Parameters>
      </Test>
      <Test Name="Test6" Namespace="TestCases">
            <Parameters>
              <Parameter Type="Dev" Name="Dev">
                <Requirements>
                  <Requirement TypeId="a76" Source="User" />
                  <Requirement TypeId="2c9" Source="User" />
                </Requirements>
              </Parameter>
              <Parameter Type="Integer" Name="expected amount of images" Value="10" />
            </Parameters>
      </Test>
   </Children>
  </Group>
  <Models>
    <Model Name="DD1" />
  </Models>
</TestSuite>

我想根据 CSV 文件订购 xml 文件。我是python的初学者。我怎么能在python中做到这一点?提前致谢

期望的输出:-

<?xml version="1.0"?>
<TestSuite Name="DM123">
  <Group Name="TestRoot" ExecutionPolicy="AnyDeviceAnyOrder">
    <Parameters>
      <Parameter Type="Integer" Name="maxA" Value="1" />
      <Parameter Type="Integer" Name="MaxB" Value="120" />
      <Parameter Type="String" Name="MaxC" Value="integration" />
    </Parameters>
    <Children>
      <Test Name="Test5" Namespace="TestCases">
        <Parameters>
           <Parameter Type="Dev" Name="Dev">
               <Requirements>
                 <Requirement TypeId="a76" Source="User" />
                 <Requirement TypeId="2c9" Source="User" />
               </Requirements>
           </Parameter>
        </Parameters>
      </Test>
      <Test Name="Test1" Namespace="TestCases">
        <Parameters>
           <Parameter Type="Device" Name="Device">
             <Requirements>
               <Requirement TypeId="a76" Source="User" />
               <Requirement TypeId="2c9" Source="User" />
             </Requirements>
           </Parameter>
        </Parameters>
      </Test>
      <Test Name="Test6" Namespace="TestCases">
            <Parameters>
              <Parameter Type="Dev" Name="Dev">
                <Requirements>
                  <Requirement TypeId="a76" Source="User" />
                  <Requirement TypeId="2c9" Source="User" />
                </Requirements>
              </Parameter>
              <Parameter Type="Integer" Name="expected amount of images" Value="10" />
            </Parameters>
      </Test>
   </Children>
  </Group>
  <Models>
    <Model Name="DD1" />
  </Models>
</TestSuite>

【问题讨论】:

标签: python xml csv xml-parsing


【解决方案1】:

您可以为此使用 XML 阅读器,但这是一种相对简单的排序,您可以通过列表切片来完成。有关实现的详细信息,请参见代码中的 cmets。

注意:我假设未使用 CSV 映射文件的第一列。如果将其用于排序顺序而不是行的顺序,请告诉我。这是对下面代码的简单调整...

import csv


def load_csv_map(filename: str) -> list:
    """load a CSV file and return a list with the test order"""
    result = []
    with open(filename) as infile:
        # since the CSV file looks like a tab-delimited CSV file
        # we need to set the delimiter to '\t'
        # we also skip the first line using slicing [1:]
        # as this first line contains the column names
        # and it doesn't look like you need them
        reader = csv.reader(infile.readlines()[1:], delimiter="\t")
    for row in reader:
        # try-except block just to catch IndexError in case the file
        # contains an empty last line.
        # whether or not it does really depends on the way the CSV file is
        # generated.
        try:
            # we only need the 2nd column, based on the provided
            # information. Note the columns are zero-indexed
            result.append(row[1])
        except IndexError as e:
            # catch the IndexError to print it out, and just continue
            print(e)
            continue
    return result


def reorder_xml_file(infilename, outfilename: str, sortorder: list) -> None:
    """read xml file and reorder children based on sortorder"""
    # I'm explicitly not using and kind of XML parser as it's quite easy to
    # do the sorting with some list magic
    with open(infilename) as infile:
        inputdata = infile.readlines()

    # get indexes of the start and end of the Children element
    # put the test elements in a dict of lists for later sorting
    testelements = {}
    for index, line in enumerate(inputdata):
        if "<Children>" in line:
            childrenstartindex = index
        elif "</Children>" in line:
            childrenendindex = index
        elif "<Test Name=" in line:
            # store the element start index and name for later use
            teststartindex = index
            # element name is easy to get as it's between the 1st and
            # second " character
            elementname = line.split('"')[1]
        elif "</Test>" in line:
            # add the element to the dict as a list
            # note the + 1 offset
            testelements[elementname] = inputdata[teststartindex : index + 1]

    # start creating the output, again with the + 1 offset
    outputdata = inputdata[: childrenstartindex + 1]
    # go through the sortorder and extend the outputdata based on that
    for elementname in sortorder:
        outputdata.extend(testelements[elementname])
    # finally extend the outputdata with the last part of the input XML file
    outputdata.extend(inputdata[childrenendindex:])

    # write the now sorted file
    with open(outfilename, "w") as outfile:
        outfile.writelines(outputdata)


sortorder = load_csv_map("path/to/file/mapping.csv")
xmlinputfilename = "path/to/file/xmlinput.xml"
xmloutputfilename = "path/to/file/xmloutput.xml"

reorder_xml_file(xmlinputfilename, xmloutputfilename, sortorder)

【讨论】:

  • 你好江户。谢谢你的回复。如果代码对我有用,我会在某个时候告诉你。
猜你喜欢
  • 2021-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多