问问题
368 次
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 用户的示例数据,请参阅在线演示,其中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)
于 2019-10-18T21:35:17.567 回答