Python ElementTree XML修改具有多个值的元素

时间:2016-03-13 23:54:32

标签: python xml lxml

使用Python 2.7和lxml,如何修改具有多个值的XML元素?

E.g。

    <Title>
      <Playcount>1</Playcount>
      <Genre>Adventure</Genre>
      <Genre>Comedy</Genre>
      <Genre>Action</Genre>
    </Title>

可以直接修改Playcount,因为它只有一个值。如何修改Genre,具有多个值?

e.g:

  1. 如何删除除第一种类型之外的所有类型?

  2. 如何添加流派?

  3. 如何将所有棒球类型修改为体育?
  4. 感谢。

2 个答案:

答案 0 :(得分:2)

喜欢这个::

$_POST['studentnumber']

新游戏数量:

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)

答案 1 :(得分:1)

在负责操作原始XML文件时考虑使用XSLT解决方案。正如在PHP question上提到的那样,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可以移植到其他语言/平台。

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() &gt; 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()

结果 (请注意以下所有上述问题,除了已发布数据中没有的棒球外)

<?xml version='1.0' encoding='UTF-8'?>
<Title>
  <Playcount>newvalue</Playcount>
  <Genre>Adventure</Genre>
  <Genre>new</Genre>
</Title>