为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用python修改xml文件中嵌套元素的文本?

如何使用python修改xml文件中嵌套元素的文本?

鸿蒙传说 2022-06-28 16:47:19
目前我正在研究一个语料库/数据集。它是 xml 格式,如下图所示。我面临一个问题。我想一一访问所有'ne'元素,如下图所示。然后我想访问'ne'元素内的'W'元素的文本。然后我想将你的符号'SDi'和'EDi'与这些'W'元素的文本连接起来。'i' 可以取从 1 开始的任何正整数。在 'SDi' 的情况下,我只需要在 'ne' 元素内的第一个 'W' 元素的文本。在“EDi”的情况下,我只需要最后一个“W”元素的文本那是在'ne'元素内。目前我在运行代码后没有得到任何输出。我认为这是因为元素“W”从未被访问过。此外,我认为元素'W'未被访问,因为它是元素'ne'的孙子,因此它不能直接访问,而是在其父节点的帮助下可能是可能的。注1:“ne”元素中子元素的个数和名称不相同。注2:这里只说明需要的东西。您可能会在编码/图片中找到一些其他细节,但忽略它们。我正在使用 Spyder (python 3.6) 任何帮助将不胜感激。我正在处理的 XML 文件中的图片如下所示:XML文件的文本版本: 点击这里示例/预期输出图像(下):到目前为止我所做的编码:for i in range(len(List_of_root_nodes)):true_false = Truecurrent = List_of_root_nodes[i]start_ID = current.PDante_ID#print('start:', start_ID)  # For Testingend_ID = Nonenumber = str(i+1)  # This number will serve as i used with SD and ED that is (SDi and EDi)discourse_starting_symbol = "SD" + numberdiscourse_ending_symbol = "ED" + numberwhile true_false:        if current.right_child is None:                end_ID = current.PDante_ID        #print('end:', end_ID)  # For Testing        true_false = False            else:                current = current.right_child# Finding 'ne' element with id='start_ID'ne_text = Nonene_id = Nonefor ne in myroot.iter('ne'):        ne_id = ne.get('id')    # If ne_id matches with start_ID means the place where SDi is to be placed is found        if ne_id == start_ID:                for w in ne.iter('W'):                        ne_text = str(w.text)                        boundary_and_text = " " + str(discourse_starting_symbol) + " " + ne_text            w.text = boundary_and_text            break
查看完整描述

2 回答

?
慕标5832272

TA贡献1966条经验 获得超4个赞

像这样(a.xml 是您上传的 XML):


请注意,代码没有使用任何外部库。


import xml.etree.ElementTree as ET


SD = 'SD'

ED = 'ED'


root = ET.parse('a.xml')


counter = 1


for ne in root.findall('.//ne'):

    w_lst = ne.findall('.//W')

    if w_lst:

        w_lst[0].text = '{}{} {}'.format(SD, counter, w_lst[0].text)

        if len(w_lst) > 1:

            w_lst[-1].text = '{} {}{}'.format(w_lst[-1].text, ED, counter)

        counter += 1

ET.dump(root)


查看完整回答
反对 回复 2022-06-28
?
元芳怎么了

TA贡献1798条经验 获得超7个赞

每当您需要修改具有各种细微差别的 XML 时,请考虑XSLT,这是一种专门用于转换 XML 文件的语言。您可以使用 Python 的第三方模块lxml(不是内置的etree)运行 XSLT 1.0 脚本。


具体来说,调用身份转换以按原样复制 XML,然后运行两个模板以添加SDI到第一个<W>和最后一个 EDI 的文本到最后一个文本<W>。如果有 10 或 10,000 个<W>节点,无论是否深度嵌套,解决方案都会起作用。


要演示 StackOverflow 的顶级 Python 和 XSLT 用户的示例数据,请参阅在线演示,其中SDI和EDI添加到第一个和最后一个<user>节点:


XSLT (另存为 .xsl 文件,在 Python 中加载的特殊 .xml 文件)


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes"/>

  <xsl:strip-space elements="*"/>


  <!-- IDENTITY TRANSFORM -->    

  <xsl:template match="@*|node()">

    <xsl:copy>

      <xsl:apply-templates select="@*|node()"/>

    </xsl:copy>

  </xsl:template>


  <!-- EDIT FIRST W NODE -->    

  <xsl:template match="W[count(preceding::W)=0]">

    <xsl:copy>

      <xsl:copy-of select="@*"/>

      <xsl:value-of select="concat('SDI ', text())"/>

    </xsl:copy>

  </xsl:template>


  <!-- EDIT LAST W NODE -->    

  <xsl:template match="W[count(preceding::W)+1 = count(//W)]">

    <xsl:copy>

      <xsl:copy-of select="@*"/>

      <xsl:value-of select="concat('EDI ', text())"/>

    </xsl:copy>

  </xsl:template>


</xsl:stylesheet>

Python (无循环或 if/else 逻辑)


import lxml.etree as et


doc = et.parse('/path/to/Input.xml')

xsl = et.parse('/path/to/Script.xsl')


# CONFIGURE TRANSFORMER

transform = et.XSLT(xsl)    


# TRANSFORM SOURCE DOC

result = transform(doc)


# OUTPUT TO CONSOLE

print(result)


# SAVE TO FILE

with open('Output.xml', 'wb') as f:

    f.write(result)


查看完整回答
反对 回复 2022-06-28
  • 2 回答
  • 0 关注
  • 165 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号