0
4

2 回答 2

1

像这样(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)
于 2019-10-19T07:28:49.513 回答
1

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

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

要演示 StackOverflow 的顶级 Python 和 XSLT 用户的示例数据,请参阅在线演示,其中SDIEDI添加到第一个和最后一个<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)
于 2019-10-18T21:35:17.567 回答