Here is how to do it by using XSLT.
It is using a so called Identity Transform pattern.
I had to fix the XML sample to make it well-formed:
- Opening and closing XML elements were not matching.
- Attribute values were not enclosed by quotes.
Input XML
<A>
<B>
<C>text</C>
<D>text2</D>
<E a="v1" b="v2">
<F>v3</F>
</E>
</B>
</A>
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8"
omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="v1" select="'v1_new'"/>
<xsl:param name="v2" select="'v2_new'"/>
<xsl:param name="v3" select="'v3_new'"/>
<!--Identity Transform pattern-->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="E/@a">
<xsl:attribute name="a">
<xsl:value-of select="$v1"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="E/@b">
<xsl:attribute name="b">
<xsl:value-of select="$v2"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="F/text()">
<xsl:value-of select="$v3"/>
</xsl:template>
</xsl:stylesheet>
Output XML
<A>
<B>
<C>text</C>
<D>text2</D>
<E a="v1_new" b="v2_new">
<F>v3_new</F>
</E>
</B>
</A>
Python
import os
import lxml.etree as ET
inputfile = "D:\\temp\\input.xml"
xsltfile = "D:\\temp\\process.xslt"
outfile = "D:\\output\\output.xml"
dom = ET.parse(inputfile)
xslt = ET.parse(xsltfile)
transform = ET.XSLT(xslt)
newdom = transform(dom,
v1=XSLT.strparam("bk101"),
v2=XSLT.strparam("New Author"))
infile = unicode((ET.tostring(newdom, pretty_print=True)))
outfile = open(outfile, 'a')
outfile.write(infile)