Tiger1
Tiger1

Reputation: 1377

How to build an xml template with variable attributes from scratch

My goal is to build an xml template with placeholders for variable attributes. for some reasons, the template would not take in new data into its placeholders.

Here's an example:

x=2*5
xmlTemplate="""
<personal reference="500.txt">
    <others:sequence>
        <feature:name="name" age="age" dob="dob"/>
    </others:sequence>
</personal>""".format(name='Michael', age=x, dob=15/10/1900)
print xmlTemplate

Output:

<personal reference="500.txt">
    <others:sequence>
        <feature:name="name" age="age" dob="dob"/>
    </others:sequence>
</personal>

Ideal output:

<personal reference="500.txt">
    <others:sequence>
        <feature:name="Michael" age="10" dob="15/10/1900"/>
    </others:sequence>
</personal>

Any ideas? Thanks.

Upvotes: 3

Views: 2075

Answers (2)

John Smith Optional
John Smith Optional

Reputation: 24836

To create an XML document in Python, it seems easier to use the Yattag library.

from yattag import Doc

doc, tag, text = Doc().tagtext()

x = 2*5

with tag('personal', reference = "500.txt"):
    with tag('others:sequence'):
        doc.stag('feature', name = "Michael", age = str(x), dob = "15/10/1900")

print(doc.getvalue())

When run, the above code will generate the following XML:

<personal reference="500.txt">
  <others:sequence>
    <feature name="Michael" age="10" dob="15/10/1900" />
  </others:sequence>
</personal>

Note: Indentation was added to the example above for readability, as getvalue returns a single line without spaces between tags. To produce a formatted document, use the indent function.

Upvotes: 4

unutbu
unutbu

Reputation: 879411

Your template needs curly braces:

x=2*5
xmlTemplate="""
<personal reference="500.txt">
    <others:sequence>
        <feature:name="{name}" age="{age}" dob="{dob}"/>
    </others:sequence>
</personal>""".format(name='Michael', age=x, dob='15/10/1900')
print xmlTemplate

yields

<personal reference="500.txt">
    <others:sequence>
        <feature:name="Michael" age="10" dob="15/10/1900"/>
    </others:sequence>
</personal>

The format method replaces names in curly-braces. Compare, for example,

In [20]: 'cheese'.format(cheese='Roquefort')
Out[20]: 'cheese'

In [21]: '{cheese}'.format(cheese='Roquefort')
Out[21]: 'Roquefort'

I see you have lxml. Excellent. In that case, you could use lxml.builder to construct XML. This will help you create valid XML:

import lxml.etree as ET
import lxml.builder as builder
E = builder.E
F = builder.ElementMaker(namespace='http://foo', nsmap={'others':'http://foo'})

x = 2*5
xmlTemplate = ET.tostring(F.root(
    E.personal(
        F.sequence(
            E.feature(name='Michael',
                   age=str(x),
                   dob='15/10/1900')
            ), reference="500.txt")),
                          pretty_print=True)
print(xmlTemplate)

yields

<others:root xmlns:other="http://foo">
  <personal reference="500.txt">
    <others:sequence>
      <feature dob="15/10/1900" age="10" name="Michael"/>
    </others:sequence>
  </personal>
</others:root>

and this string can be parsed by lxml using:

doc = ET.fromstring(xmlTemplate)
print(doc)
# <Element {http://foo}root at 0xb741866c>

Upvotes: 3

Related Questions