Python ElementTree XML 修改具有多个值的元素
Python ElementTree XML Modifying Elements with Multiple Values
使用 Python 2.7 和 lxml
,如何修改具有多个值的 XML 元素?
例如
<Title>
<Playcount>1</Playcount>
<Genre>Adventure</Genre>
<Genre>Comedy</Genre>
<Genre>Action</Genre>
</Title>
直接修改 Playcount
,因为它只有一个值。如何修改Genre
,有多个值?
例如:
如何删除除第一个流派以外的所有流派?
如何添加流派?
- 如何将所有棒球类型修改为运动?
谢谢。
像这样::
from lxml import etree
parser = etree.XMLParser(remove_blank_text=True)
tree = etree.fromstring("""<Title>
<Playcount>1</Playcount>
<Genre>Adventure</Genre>
<Genre>Comedy</Genre>
<Genre>Action</Genre>
<someTag>Text</someTag>
</Title>""", parser=parser)
新播放次数:
playcount = tree.find('Playcount')
playcount.text = "2"
删除流派(不是第一个):
title = tree.xpath('/Title')[0]
genres = title.xpath('Genre')
for element in genres:
if element.tag == "Genre" and element != title.xpath("Genre[1]")[0]:
element.getparent().remove(element)
新类型:
genre = etree.Element("Genre")
genre.text = "New Genre"
tree.xpath('/Title/Genre[last()]')[0].addnext(genre)
结果:
print etree.tostring(tree, pretty_print=True)
当任务是处理原始 XML 文件时,请考虑使用 XSLT 解决方案。正如刚刚在此 中提到的,XSLT(其脚本是一个格式良好的 XML 文件)是一种特殊用途的声明性编程语言,可以在一个脚本中处理多个任务,如下所示。
大多数通用语言,包括 Python(lxml 模块)、PHP(xsl 扩展) , Java (javax.xml), Perl (libxml), C# (System.Xml) 和 VB (MSXML) 维护 XSLT 1.0 处理器。还有各种外部可执行处理器,如 Xalan and Saxon(后者可以 运行 XSLT 2.0 和最近的 3.0)也可用 - 当然 Python 可以用 subprocess.call()
调用。
下面分别包含 XSLT 和 Python 脚本,因为前者加载到后者中。如上所述,xslt 可移植到其他 languages/platforms。
XSLT 脚本 (另存为 .xsl 或 .xslt)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<!-- IDENTITY TRANSFORM (COPY CONTENT AS IS) -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- CHANGE PLAYCOUNT -->
<xsl:template match="Playcount">
<xsl:copy>newvalue</xsl:copy>
</xsl:template>
<!-- EMPTY TEMPLATE TO REMOVE NODES BY POSITION -->
<xsl:template match="Genre[position() > 1]"></xsl:template>
<!-- ADD NEW GENRE -->
<xsl:template match="Title">
<xsl:copy>
<xsl:apply-templates/>
<Genre>new</Genre>
</xsl:copy>
</xsl:template>
<!-- CHANGE BASEBALL GENRE TO SPORTS -->
<xsl:template match="Title[Genre='Baseball']">
<xsl:copy>Sports</xsl:copy>
</xsl:template>
</xsl:transform>
Python 脚本
import lxml.etree as ET
# LOAD XML AND XSLT FILES
dom = ET.parse('Input.xml')
xslt = ET.parse('XSLTScript.xsl')
# TRANSFORM INTO DOM OBJECT
transform = ET.XSLT(xslt)
newdom = transform(dom)
# OUTPUT TO PRETTY PRINT STRING
tree_out = ET.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True)
print(tree_out.decode("utf-8"))
# SAVE AS FILE
xmlfile = open('Output.xml')
xmlfile.write(tree_out)
xmlfile.close()
结果 (注意上面的所有问题都在下面处理,除了 Baseball 没有出现在发布的数据中)
<?xml version='1.0' encoding='UTF-8'?>
<Title>
<Playcount>newvalue</Playcount>
<Genre>Adventure</Genre>
<Genre>new</Genre>
</Title>
使用 Python 2.7 和 lxml
,如何修改具有多个值的 XML 元素?
例如
<Title>
<Playcount>1</Playcount>
<Genre>Adventure</Genre>
<Genre>Comedy</Genre>
<Genre>Action</Genre>
</Title>
直接修改 Playcount
,因为它只有一个值。如何修改Genre
,有多个值?
例如:
如何删除除第一个流派以外的所有流派?
如何添加流派?
- 如何将所有棒球类型修改为运动?
谢谢。
像这样::
from lxml import etree
parser = etree.XMLParser(remove_blank_text=True)
tree = etree.fromstring("""<Title>
<Playcount>1</Playcount>
<Genre>Adventure</Genre>
<Genre>Comedy</Genre>
<Genre>Action</Genre>
<someTag>Text</someTag>
</Title>""", parser=parser)
新播放次数:
playcount = tree.find('Playcount')
playcount.text = "2"
删除流派(不是第一个):
title = tree.xpath('/Title')[0]
genres = title.xpath('Genre')
for element in genres:
if element.tag == "Genre" and element != title.xpath("Genre[1]")[0]:
element.getparent().remove(element)
新类型:
genre = etree.Element("Genre")
genre.text = "New Genre"
tree.xpath('/Title/Genre[last()]')[0].addnext(genre)
结果:
print etree.tostring(tree, pretty_print=True)
当任务是处理原始 XML 文件时,请考虑使用 XSLT 解决方案。正如刚刚在此
大多数通用语言,包括 Python(lxml 模块)、PHP(xsl 扩展) , Java (javax.xml), Perl (libxml), C# (System.Xml) 和 VB (MSXML) 维护 XSLT 1.0 处理器。还有各种外部可执行处理器,如 Xalan and Saxon(后者可以 运行 XSLT 2.0 和最近的 3.0)也可用 - 当然 Python 可以用 subprocess.call()
调用。
下面分别包含 XSLT 和 Python 脚本,因为前者加载到后者中。如上所述,xslt 可移植到其他 languages/platforms。
XSLT 脚本 (另存为 .xsl 或 .xslt)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<!-- IDENTITY TRANSFORM (COPY CONTENT AS IS) -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- CHANGE PLAYCOUNT -->
<xsl:template match="Playcount">
<xsl:copy>newvalue</xsl:copy>
</xsl:template>
<!-- EMPTY TEMPLATE TO REMOVE NODES BY POSITION -->
<xsl:template match="Genre[position() > 1]"></xsl:template>
<!-- ADD NEW GENRE -->
<xsl:template match="Title">
<xsl:copy>
<xsl:apply-templates/>
<Genre>new</Genre>
</xsl:copy>
</xsl:template>
<!-- CHANGE BASEBALL GENRE TO SPORTS -->
<xsl:template match="Title[Genre='Baseball']">
<xsl:copy>Sports</xsl:copy>
</xsl:template>
</xsl:transform>
Python 脚本
import lxml.etree as ET
# LOAD XML AND XSLT FILES
dom = ET.parse('Input.xml')
xslt = ET.parse('XSLTScript.xsl')
# TRANSFORM INTO DOM OBJECT
transform = ET.XSLT(xslt)
newdom = transform(dom)
# OUTPUT TO PRETTY PRINT STRING
tree_out = ET.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True)
print(tree_out.decode("utf-8"))
# SAVE AS FILE
xmlfile = open('Output.xml')
xmlfile.write(tree_out)
xmlfile.close()
结果 (注意上面的所有问题都在下面处理,除了 Baseball 没有出现在发布的数据中)
<?xml version='1.0' encoding='UTF-8'?>
<Title>
<Playcount>newvalue</Playcount>
<Genre>Adventure</Genre>
<Genre>new</Genre>
</Title>