如何为 Azure tts (mstts) 设置命名空间

rod*_*dbs 1 python xml elementtree xml-namespaces

我需要为 Azure TTS 创建此标头:

 <speak version="1.0" 
  xmlns="https://www.w3.org/2001/10/synthesis" 
   xmlns:mstts="https://www.w3.org/2001/mstts" 
   xml:lang="en-US">
Run Code Online (Sandbox Code Playgroud)

这是用于创建 xml:lang 键的代码:

xml_body = ElementTree.Element('speak', version='1.0')
xml_body.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-us')
Run Code Online (Sandbox Code Playgroud)

我试图创建 xmlns:mstts 没有成功。这不起作用:

xml_body.set('{https://www.w3.org/2001/10/synthesis}mstts', 'https://www.w3.org/2001/mstts' )
Run Code Online (Sandbox Code Playgroud)

因为这会产生以下输出:

 <speak version="1.0" 
  xmlns="https://www.w3.org/2001/10/synthesis" 
   xmlns:mstts="https://www.w3.org/2001/mstts" 
   xml:lang="en-US">
Run Code Online (Sandbox Code Playgroud)

请注意元素属性中的xmlns:ns0ns0:mstts问题<speak>

有任何想法吗?

Mar*_*ers 5

你需要给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')
Run Code Online (Sandbox Code Playgroud)

您还可以将属性添加为字典,作为第二个参数传入:

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'
    })
Run Code Online (Sandbox Code Playgroud)

不是需要设置xmlns:mstts但是属性!ElementTree 将根据需要根据您构建的 XML 树中使用的名称空间自动添加此属性。

确实希望使用以下函数向 ElementTree注册此命名空间:register_namespace()

ElementTree.register_namespace('mstts', 'https://www.w3.org/2001/mstts')
Run Code Online (Sandbox Code Playgroud)

这告诉 ElementTree,当您使用{https://www.w3.org/2001/mstts}带有标签名称或属性的命名空间时,将 XML 树序列mstts化为文件或字符串时,该命名空间应该用作前缀。如果您没有注册的命名空间,命名空间前缀会为你(生成ns0:ns1:等等)。这将产生完全有效的 XML,命名空间前缀是文档本地的,前缀只是完整命名空间 URI 的简写名称。任何兼容的 XML 解析器都将ns0作为https://www.w3.org/2001/mstts命名空间 URI的前缀进行处理,与 using 完全相同mstts

对于默认命名空间(例如https://www.w3.org/2001/10/synthesis<speak>元素的命名空间),请使用methoddefault_namespace参数。ElementTree.write()

我发现QName()对象更容易处理命名空间属性和标签名称;与特定命名空间的变量一起,使您不太可能打错字。这是基于 Azure SSML 文档中的示例的更完整的示例

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"])
Run Code Online (Sandbox Code Playgroud)

上面产生了以下 XML(手动漂亮打印以方便阅读):

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')
Run Code Online (Sandbox Code Playgroud)

您可能还想查看外部lxml,因为它包含一个使使用命名空间更容易的lxml.builder.ElementMaker

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",
        )
    )
)
Run Code Online (Sandbox Code Playgroud)

在上面,使用E.tagname(...)orE('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>
Run Code Online (Sandbox Code Playgroud)