【问题标题】:How to change different hierarchy tags with lxml?如何使用 lxml 更改不同的层次结构标签?
【发布时间】:2021-07-16 21:13:12
【问题描述】:

我想在 python 中使用 lxml 将所有标签名称 <p> 更改为 <PARAGRAPH>。问题是我可以更改外部概念标签的<p> 标签和第一个内部概念<p> 标签,但我不知道如何更改所有剩余的<p> 标签。

这是 xml 文件的示例。

<dita>
    <topic id="id15CDB0PL09E">
        <title id="id15CDB0R0VYB"><?FM MARKER [Header/Footer $1] All?>Control
        </title>
        <shortdesc>CONTROL</shortdesc>
        <concept id="id15CDB0Q0Q4G">
            <title id="id15CDB0R0VHA">General
            </title>
            <conbody>
                <p>This section
                </p>
            </conbody>
            <concept id="id156F7H00GIE">
                <title id="id15CDB0R0V1W">System
                </title>
                <conbody>
                    <p>Engine  
                    </p>
                    <p>The ECU 
                    </p>
                    <p>The aircraft 
                    </p>
                    <p>The system
                    </p>
               </conbody>
            </concept>
        </concept>
    </topic>
</dita>

这是我使用 lxml 的 python 代码。

# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""

from lxml import etree
doc = etree.parse("73-20.xml")

#Lista para guardar las tag que son hijas de la tag concept
conceptDentro=[]
conbodysFuera=[]
conbodysDentro=[]

#Consigue la root tag (en este caso es dita y su unico hijo es topic)
raiz = doc.getroot()
print(raiz.tag)
print("\n")

#Encuentra todos los tag concept que son hijos de la tag topic
conceptAfuera = raiz[0].findall("concept")
print(conceptAfuera)
print("\n")


#Con este ciclo encuentra las tag concept que son hijas de la tags conceptAfuera
for i in range(len(conceptAfuera)):
    #conbodysFuera son los tag conbody que son hijos de los conceptAfuera, en este caso solo hay 1
    conbodysFuera.extend(conceptAfuera[i].findall("conbody"))
    #conceptDentro son las tags concept dentro de las tag conceptAfuera
    conceptDentro.extend(conceptAfuera[i].findall("concept"))

#ConceptDentro es una lista que almacena todas las tag concept dentro de las tag conceptAfuera    
print("Etiquetas de conceptDentro: ",conceptDentro) 
print("\n")
print("Etiquetas de conbodysFuera: ",conbodysFuera)
print("\n")

#Ciclo para encontrar todas las tag conbody dentro de los conceptDentro
for i in range(len(conceptDentro)):
    conbodysDentro.extend(conceptDentro[i].findall("conbody"))

print("Etiquetas de conbodysDentro: ", conbodysDentro)
print("\n")

#Ciclo para cambiar la tag p de conbodysFuera
for i in range(len(conbodysFuera)):
    for j in range(len(conbodysFuera[i].findall("p"))):
        conbodysFuera[i].findall("p")[j].tag="PARAGRAPH"
        
#Ciclo para cambiar la tag p de conbodysDentro
for i in range(len(conbodysDentro)):
    #for j in range(len(conbodysDentro[i].findall("p"))):
        conbodysDentro[i].findall("p")[j].tag="PARAGRAPH"

#print(etree.tostring(doc, pretty_print=True, xml_declaration=True, encoding="utf-8"))
doc.write("FerNewtags.xml")

如您所见,Ciclo 的最后一个被写为注释,因为它会导致 IndexError: list index out of range

有什么想法吗?

【问题讨论】:

    标签: python xml lxml


    【解决方案1】:

    我认为你过于复杂了。只需找到所有p 元素(带有.xpath().findall())并更改.tag 属性的值...

    from lxml import etree
    
    tree = etree.parse("73-20.xml")
    
    for p in tree.findall(".//p"):
        p.tag = "paragraph"
    
    tree.write("FerNewtags.xml")
    

    输出 (FerNewtags.xml)

    <dita>
        <topic id="id15CDB0PL09E">
            <title id="id15CDB0R0VYB"><?FM MARKER [Header/Footer $1] All?>Control
            </title>
            <shortdesc>CONTROL</shortdesc>
            <concept id="id15CDB0Q0Q4G">
                <title id="id15CDB0R0VHA">General
                </title>
                <conbody>
                    <paragraph>This section
                    </paragraph>
                </conbody>
                <concept id="id156F7H00GIE">
                    <title id="id15CDB0R0V1W">System
                    </title>
                    <conbody>
                        <paragraph>Engine
                        </paragraph>
                        <paragraph>The ECU
                        </paragraph>
                        <paragraph>The aircraft
                        </paragraph>
                        <paragraph>The system
                        </paragraph>
                   </conbody>
                </concept>
            </concept>
        </topic>
    </dita>
    

    【讨论】:

    • 谢谢丹尼尔,事实上,我已经把它复杂化了。这回答了我的问题,但是如果我只想根据文本更改一些

      标签怎么办? (即

      本节

      ,以及,

      ECU

      )?
    • @AlbertoValdivia - 我确信您可以更新 xpath 以检查文本,但您将如何实际执行将取决于您需要检查文本的内容。例如,如果您想专门检查“This section”和“The ECU”,您可以使用如下内容:tree.xpath(".//p[normalize-space()='This section' or normalize-space()='The ECU']")
    猜你喜欢
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    • 2020-03-17
    • 1970-01-01
    • 2020-12-23
    • 2010-09-12
    相关资源
    最近更新 更多