首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用ElementTree在Python中创建多层次的继承XML树

使用ElementTree在Python中创建多层次的继承XML树
EN

Stack Overflow用户
提问于 2020-11-11 20:40:59
回答 1查看 250关注 0票数 0

因此,将输入作为txt文件,我们必须创建XML树或任何层次结构,以便更容易地进行解析。然后找到上一任CEO的最后一位雇员。

txt给出了列按以下顺序排列的公司结构:名称、工资、雇主。那些以“无人”为雇主的人是公司的首席执行官。具有雇主名称的txt位于上述雇主之下。txt看起来如下所示:

代码语言:javascript
运行
复制
Vineel Phatak, 520, NOBODY
Ajay Joshi, 250, Vineel Phatak
Abhishek Chauhan, 120, Ajay Joshi
Jayesh Godse, 500, NOBODY
Vijaya Mundada, 60, Abhishek Chauhan
Shital Tuteja, 45, Jayesh Godse
Rajan Gawli, 700, Vineel Phatak
Zeba Khan, 300, Jayesh Godse
Chaitali Sood, 100, Zeba Khan
Sheila Rodrigues, 35, Vineel Phatak

因此,我们必须做到这样的事情:

代码语言:javascript
运行
复制
Company
->Vineel Phatak
-->Ajay Joshi
--->Abhishek Chauhan
---->Vijaya Mundada
-->Rajan Gawli
-->Sheila Rodrigues

->Jayesh Godse
-->Shital Tuteja
-->Zeba Khan
--->Chaitali Sood

XML格式:

代码语言:javascript
运行
复制
<company>
    <Vineel Phatak>
        <Ajay Joshi>
            <Abhishek Chauhan>
                <Vijaya Mundada />
            </Abhishek Chauhan>
        </Ajay Joshi>
        <Rajan Gawli />
        <Sheila Rodrigues />
    </Vineel Phatak>

    <Jayesh Godse>
        <Shital Tuteja />
        <Zeba Khan>
            <Chaitali Sood />
        </Zeba Khan>
    </Jayesh Godse>
</company>

我试图做的是,在创建了一个名为company的元素之后,因为我们需要向根(Company)添加子元素,所以我尝试生成这些元素并将其附加到列表中。然后对列表进行解析并进行比较以获得值。

代码语言:javascript
运行
复制
# Find last employee of the last introduced CEO
import xml.etree.ElementTree as ET

# Reading Input
inD = open('input.txt', 'r')
data = inD.readlines()
inD.close()

# Creating an element and saving all subelement to list
all_element = []
company = ET.Element('Company')
ceos = []
for i in data:
    t = i.strip().split(',')
    if(t[2].strip() == 'NOBODY'):
        ceos.append(t[0])
    all_element.append(ET.SubElement(company, t[0]))
# company.clear()
# Creating a function to add subelements
def findChilds(name, emp):
    global all_element
    for i in all_element:
        if emp == i.tag:
            name = ET.SubElement(i, name)

# If it is CEO hence no emplyer then directly add subelement to company or else add to the previous subelement
for j in data:
    t = j.strip().split(',')
    if t[2].strip() == 'NOBODY':
        e = ET.SubElement(company, t[0])
    elif t[2].strip() != 'NOBODY':
        findChilds(t[0].strip(), t[2].strip())
        
ET.dump(company)

结果如下:

代码语言:javascript
运行
复制
<Company><Vineel Phatak><Ajay Joshi /><Rajan Gawli /><Sheila Rodrigues /></Vineel Phatak><Ajay Joshi><Abhishek Chauhan /></Ajay Joshi><Abhishek Chauhan><Vijaya Mundada /></Abhishek Chauhan><Jayesh Godse><Shital Tuteja /><Zeba Khan /></Jayesh Godse><Vijaya Mundada /><Shital Tuteja /><Rajan Gawli /><Zeba Khan><Chaitali Sood /></Zeba Khan><Chaitali Sood /><Sheila Rodrigues /><Vineel Phatak /><Jayesh Godse /></Company>

你看得出来不完全正确。还删除了元素(第18行),因为它拒绝添加除ceos以外的其他子元素

最后,我们需要创建这个层次结构,然后打印出上一任首席执行官的最后一个雇员的名字,在本例中是:

最后一任首席执行官: Jayesh Godse

首席执行官的最后一位雇员(直接或间接,最后从输入中介绍):Chaitali Sood

代码语言:javascript
运行
复制
Output:
Chaitali Sood

还有首席执行官的人数和他们下面的孩子和GrandChildren的数量还不确定,名字也不确定。。

我是ElementTree的新手,所以可能有一些我不知道的预定义函数,所以请原谅我的无知。深刻的见解和建议是非常感谢的。提前感谢!

EN

回答 1

Stack Overflow用户

发布于 2020-11-19 13:47:22

在列出我的示例之前,请注意xml结构:在创建xml结构时,更好的做法是对元素的标记使用“object的类”,并将其“属性”存储为xml属性,如名称和薪水:

<employee name="Vineel Phatak" salary="520"/>

而不是:

<Vineel Phatak/>

这将使解析更加容易,并为扩展格式提供了更大的灵活性。

我的例子

为您的问题提供一个示例实现:

代码语言:javascript
运行
复制
import csv
from dataclasses import dataclass
import xml.etree.ElementTree as ET


@dataclass
class Employee:
    linenumber: int
    name: str
    salary: str
    manager_name: str
    subordinates: list


employees = {}  # a dictionary to map names to employees

# load employees
with open('company.csv') as csvfile:
    reader = csv.reader(csvfile)
    for linenumber, row in enumerate(reader):
        (name, salary, manager_name) = [value.strip() for value in row]
        employees[name] = Employee(linenumber, name, salary, manager_name, [])


# link employees to their subordinates
ceos = []
for employee in employees.values():
    if employee.manager_name == 'NOBODY':
        # store the ceos in a list to start building the xml from later
        ceos.append(employee)
    else:
        # look up the manager by it name
        manager = employees[employee.manager_name]
        manager.subordinates.append(employee)

# create xml
companyelement = ET.Element('company')

def add_employees_to_xml_element(xmlelement, employees):
    for employee in employees:
        employee_element = ET.Element("employee", {
            "name": employee.name,
            "salary": employee.salary
        })
        xmlelement.append(employee_element)
        add_employees_to_xml_element(employee_element, employee.subordinates)


add_employees_to_xml_element(companyelement, ceos)
ET.dump(companyelement)

# find the last entered ceo
def linenumber_key(ceo): return ceo.linenumber


last_entered_ceo = max(ceos, key=linenumber_key)
print(f"Last entered CEO: {last_entered_ceo.name}")

# find the last entered (in)direct subordinate of the last entered ceo
def find_last_entered_subordinate(employee, current_last=None):
    for subordinate in employee.subordinates:
        if not current_last:
            current_last = subordinate  # ensuring an initial value
        else:
            current_last = max([current_last, subordinate], key=linenumber_key)
        # recursive: travers the subordinate's subordinates
        current_last = find_last_entered_subordinate(subordinate, current_last)
    return current_last


last_employee = find_last_entered_subordinate(last_entered_ceo)
print(f"Last added subordinate of last CEO: {last_employee.name}")

我把节目单分成以下几部分:

  1. Load Employees从CSV文件到字典,以方便(并加快)查找员工的名字。我还存储每个员工的行号,供您以后的questions.
  2. Link员工使用给他们的下属。假设经理可能会被列在他们的下属之后,这不能在第一步中结合起来。每个员工都会有一个下属的列表,CEO将使用元素树存储在一个独立的“根”list.
  3. Create xml中,并使用一个递归函数遍历上面创建的CEO list.
  4. Find (上一次输入的CEO )。我们已经有了一个CEO列表,但是因为它是从字典中创建的(这不能确保元素按照添加的顺序被检索),我不能只使用最后一个元素,而是应该找到linenumber.
  5. Find最高的首席执行官--上一个输入的( in )直接从属于上一个进入的首席执行官。与上面类似,这次我使用了一个递归函数来根据linenumber.

检索这个雇员。

由此产生的xml:

代码语言:javascript
运行
复制
<company>
    <employee name="Vineel Phatak" salary="520">
        <employee name="Ajay Joshi" salary="250">
            <employee name="Abhishek Chauhan" salary="120">
                <employee name="Vijaya Mundada" salary="60"/>
            </employee>
        </employee>
        <employee name="Rajan Gawli" salary="700"/>
        <employee name="Sheila Rodrigues" salary="35"/>
    </employee>
    <employee name="Jayesh Godse" salary="500">
        <employee name="Shital Tuteja" salary="45"/>
        <employee name="Zeba Khan" salary="300">
            <employee name="Chaitali Sood" salary="100"/>
        </employee>
    </employee>
</company>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64793820

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档