您需要给speak 元素一个命名空间,以及它的version 属性,这就是xmlns="..." 属性通常配置的内容。为此使用{<namespaceuri>}<tagname> 限定名称格式,就像您为xml:lang 属性所做的那样:
xml_body = ElementTree.Element('{https://www.w3.org/2001/10/synthesis}speak')
xml_body.set('{https://www.w3.org/2001/10/synthesis}version', '1.0')
xml_body.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-us')
您还可以将属性添加为字典,作为第二个参数传入:
xml_body = ElementTree.Element(
'{https://www.w3.org/2001/10/synthesis}speak', {
'{https://www.w3.org/2001/10/synthesis}version': '1.0',
'{http://www.w3.org/XML/1998/namespace}lang': 'en-us'
})
您确实不需要需要设置xmlns:mstts 属性,但是! ElementTree 将根据您构建的 XML 树中使用的命名空间,根据需要自动添加此属性。
您确实想使用register_namespace() function 向ElementTree 注册这个命名空间:
ElementTree.register_namespace('mstts', 'https://www.w3.org/2001/mstts')
这告诉 ElementTree,当您使用带有标记名称或属性的 {https://www.w3.org/2001/mstts} 命名空间时,当将 XML 树序列化为文件或字符串时,该命名空间应该使用 mstts 作为前缀。如果您不注册命名空间,则会为您生成命名空间前缀(ns0:、ns1: 等)。这将产生完全有效的 XML,命名空间前缀是文档本地的,前缀只是完整命名空间 URI 的简写名称。任何兼容的 XML 解析器都会处理 ns0 作为 https://www.w3.org/2001/mstts 命名空间 URI 的前缀,这与使用 mstts 完全相同。
对于 默认 命名空间(例如根 <speak> 元素的 https://www.w3.org/2001/10/synthesis 命名空间),使用 default_namespace 参数作为 ElementTree.write() method。
我发现QName() objects 处理命名空间属性和标签名称更容易;与特定命名空间的变量一起,使您不太可能打错字。这是一个更成熟的例子based on an example from the Azure SSML documentation
from xml.etree import ElementTree as ET
from functools import partial
ns = {
"synthesis": "https://www.w3.org/2001/10/synthesis",
"mstts": "https://www.w3.org/2001/mstts",
"xml": "http://www.w3.org/XML/1998/namespace",
}
ET.register_namespace('mstts', ns['mstts'])
synthesis = partial(ET.QName, ns["synthesis"])
mstts = partial(ET.QName, ns["mstts"])
xml_ = partial(ET.QName, ns["xml"])
xml_body = ET.Element(synthesis('speak'), {
synthesis('version'): '1.0',
xml_('lang'): 'en-us',
})
voice = ET.SubElement(xml_body, synthesis('voice'), {
synthesis('name'): 'en-US-JessaNeural'})
express_as = ET.SubElement(voice, mstts('express-as'), {
mstts('type'): 'cheerful'})
express_as.text = "That'd be just amazing!"
root = ET.ElementTree(xml_body)
root.write("filename.xml", encoding="UTF-8", default_namespace=ns["synthesis"])
上面生成了以下 XML(为了便于阅读手动打印):
<speak
xmlns="https://www.w3.org/2001/10/synthesis"
xmlns:mstts="https://www.w3.org/2001/mstts"
version="1.0"
xml:lang="en-us">
<voice name="en-US-JessaNeural">
<mstts:express-as mstts:type="cheerful">
That'd be just amazing!
</mstts:express-as>
</voice>
</speak>
您可能还想查看external lxml library,因为它包含一个lxml.builder.ElementMaker class,这使得使用命名空间更加容易。
lxml 通常具有更好的命名空间支持,并且已经具有命名空间的元素的属性不需要用命名空间本身显式限定。您可以通过在设置命名空间的字典中使用前缀 None 将给定的命名空间映射标记为默认值:
from lxml import etree as ET
from lxml.builder import ElementMaker
ns = {
None: "https://www.w3.org/2001/10/synthesis",
"mstts": "https://www.w3.org/2001/mstts",
}
E = ElementMaker(namespace=ns[None], nsmap=ns)
TTS = ElementMaker(namespace=ns['mstts'])
xml_body = E.speak(
{"version": "1.0",
"{http://www.w3.org/XML/1998/namespace}lang": "en-US"},
E.voice(
{"name": "en-US-JessaNeural"},
TTS.express_as(
"That'd be just amazing!",
type="cheerful",
)
)
)
在上面,使用E.tagname(...) 或E('tagname', ...) 将使用https://www.w3.org/2001/10/synthesis 命名空间URI 创建一个元素,而MSTTS 对象使用https://www.w3.org/2001/mstts 命名空间URI 创建标签。因为我们为 E 提供了一个名称空间映射,其中 None 映射到 https://www.w3.org/2001/10/synthesis 名称空间 URI,所以该 URI 将用作默认名称空间,并且该名称空间中的标记名和属性将不加前缀。
您可以将属性作为关键字参数 (E.tagname(..., attributename="value")) 或通过作为位置参数传入的字典传入。任何包含的元素都可以简单地添加为位置参数,包括文本。您还可以添加普通的Element 方法(例如Element.append() 添加子元素,或Element.text = ... 设置指示标签的文本内容是什么)。
使用 lxml 的演示:
>>> from lxml import etree as ET
>>> from lxml.builder import ElementMaker
>>> ns = {
... None: "https://www.w3.org/2001/10/synthesis",
... "mstts": "https://www.w3.org/2001/mstts",
... }
>>> E = ElementMaker(namespace=ns[None], nsmap=ns)
>>> TTS = ElementMaker(namespace=ns['mstts'])
>>> xml_body = E.speak(
... {"version": "1.0",
... "{http://www.w3.org/XML/1998/namespace}lang": "en-US"},
... E.voice(
... {"name": "en-US-JessaNeural"},
... TTS.express_as(
... "That'd be just amazing!",
... type="cheerful",
... )
... )
... )
>>> print(ET.tostring(xml_body, encoding="unicode", pretty_print=True))
<speak xmlns="https://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" version="1.0" xml:lang="en-US">
<voice name="en-US-JessaNeural">
<mstts:express_as type="cheerful">That'd be just amazing!</mstts:express_as>
</voice>
</speak>