如何从零构建具有可变属性的XML模板

3 投票
2 回答
1956 浏览
提问于 2025-04-18 01:36

我的目标是创建一个xml模板,这个模板里有一些占位符,用来放不同的属性值。但是出于某些原因,这个模板无法把新数据放进这些占位符里。

这里有个例子:

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

输出结果:

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

理想的输出结果:

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

有什么想法吗?谢谢。

2 个回答

4

在Python中创建XML文档,使用Yattag库似乎更简单。

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())

运行上面的代码后,会生成以下XML:

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

注意:为了让例子更易读,上面的代码添加了缩进,因为getvalue返回的是一行,没有标签之间的空格。如果想要生成格式化的文档,可以使用indent函数

3

你的模板需要用大括号:

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

会得到

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

格式化方法会把大括号里的名字替换掉。比如说,看看这个:

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

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

我看到你有 lxml。太好了。在这种情况下,你可以使用 lxml.builder 来构建 XML。这样可以帮助你创建有效的 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)

会得到

<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>

而这个字符串可以用 lxml 解析,方法是:

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

撰写回答