把一个新的父母带到特殊的孩子身边

时间:2016-10-27 22:57:04

标签: python xml python-3.x

我有两个XML文件。它们非常相似。

第一个:

<a>
  <b />
  ...
  <c e='very important'>
    <d e='bla' />
    <d e='bla' />
  </c>
</a>

和第二个:

<a>
  <f />
  ...
  <d e='some' />
  <d e='values' />
</a>

我必须修改第二个XML,将第一个XML中的 c 标记复制到第二个XML中并用它包装所有 d 兄弟。我想得到类似的东西:

<a>
  <f />
  ...
  <c e='very important'>
    <d e='some' />
    <d e='values' />
  </c>
</a>

怎么做?

编辑

我的尝试很少:

import xml.etree.ElementTree as ET

f_tree = ET.parse(f_file)
s_tree = ET.parse(s_file)
f_root = f_tree.getroot()
s_root = s_tree.getroot()

one_c = f_root.find('c')
all_d = s_root.findall('d')

for child in one_c:
    one_c.remove(child)

for the_d in all_d:
    one_c.append(the_d)

1 个答案:

答案 0 :(得分:0)

虽然可能存在内置xml.etree的解决方案,可能涉及循环逻辑或复制树,但请考虑使用Python的第三方模块lxml的XSLT 1.0解决方案。 / p>

作为背景,XSL系列的一部分包含XPath,XSLT是一种用于转换XML文档的专用语言。 XSLT维护document()函数,允许您跨文档创建相对于当前XML源的XPath表达式。

下面假设所有XML和XSL文档都在同一目录中。另请注意,如图所示,XSLT脚本是格式良好的XML文件,可以像任何其他XML一样进行解析。

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="*"/>

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

  <xsl:template match="a">
    <xsl:copy>
       <xsl:copy-of select="*[local-name()!='d']"/>       
       <c>
           <xsl:copy-of select="document('f_file.xml')/a/c/@*"/>
           <xsl:copy-of select="d"/>
       </c>
    </xsl:copy>
  </xsl:template>

</xsl:transform>

Python 脚本

import os
import lxml.etree as ET

f_tree = ET.parse('f_file.xml')
s_tree = ET.parse('s_file.xml')

xslt = ET.parse('XSLT_Script.xsl')

transform = ET.XSLT(xslt)
newdom = transform(s_tree)

# PRINT TO SCREEN
print(newdom)

# <?xml version="1.0"?>
# <a>
#   <f/>
#   <other/>
#   <c e="very important">
#     <d e="some"/>
#     <d e="values"/>
#   </c>
# </a>

# OUTPUT TO FILE
with open('Output.xml', 'wb') as f:
    f.write(newdom)