【问题标题】:How to set up namespaces for Azure tts (mstts)如何为 Azure tts (mstts) 设置命名空间
【发布时间】:2020-02-08 20:33:37
【问题描述】:

我需要为 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">

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

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

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

xml_body.set('{https://www.w3.org/2001/10/synthesis}mstts', 'https://www.w3.org/2001/mstts' )

因为这会产生以下输出:

<speak
 xmlns:ns0="https://www.w3.org/2001/10/synthesis"
 version="1.0"
 xml:lang="en-us"
 ns0:mstts="https://www.w3.org/2001/mstts" />

注意&lt;speak&gt; 元素属性中的xmlns:ns0ns0:mstts 问题。

有什么想法吗?

【问题讨论】:

  • 不工作怎么办?相反会发生什么?您看到了什么输出,该输出有什么问题?

标签: python xml xml-namespaces elementtree


【解决方案1】:

您需要给speak 元素一个命名空间,以及它的version 属性,这就是xmlns="..." 属性通常配置的内容。为此使用{&lt;namespaceuri&gt;}&lt;tagname&gt; 限定名称格式,就像您为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 完全相同。

对于 默认 命名空间(例如根 &lt;speak&gt; 元素的 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>

【讨论】:

  • 我第一次看到这个条目,但它被删除了。它对我有用,我发现它更容易:` xml_body = ET.Element('speak', version='1.0', xmlns="w3.org/2001/10/synthesis") xml_body.set('{w3.org/XML/1998/namespace}lang', 'en-我们') xml_body.set('xmlns:mstts', 'w3.org/2001/mstts') `
  • @rodbs:另一个用户在我之前发布了一个答案,随后被否决了,发帖人再次删除了它。我对那个帖子给出了反馈;他们手动添加了xmlns:msttsxml:lang 属性,这实际上破坏了正确的命名空间处理。
  • @rodbs:它可能起初看起来更容易,但它会导致难以追溯的拼写错误和错误。
  • 我不明白为什么我这样做:body= ET.tostring(xml_body)print(body) 我得到了:&lt;ns0:speak xmlns:mstts="https://www.w3.org/2001/mstts" xmlns:ns0="https://www.w3.org/2001/10/synthesis" xml:lang="en-us" ns0:version="1.0"&gt; &lt;ns0:voice ns0:name="en-US-JessaNeural"&gt; &lt;mstts:express-as mstts:type="cheerful"&gt; That\'d be just amazing! &lt;/mstts:express-as&gt; &lt;/ns0:voice&gt; &lt;/ns0:speak&gt;
  • @rodbs:如果您改用lxml,那么使用带有None 键的nsmap 字典参数可以设置用于树的任何部分的默认命名空间,因为该库只是在命名空间处理方面要好得多。这就是为什么我也包含了一个完整的 ElementMaker 示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-31
  • 2011-02-21
  • 2011-10-12
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多