如何使用Python将名称空间和前缀插入XML字符串?

时间:2015-08-06 19:22:06

标签: python xml elementtree xml.etree

假设我有一个XML字符串:

<A>
    <B foo="123">
        <C>thing</C>
        <D>stuff</D>
    </B>
</A>

我希望插入XML Schema使用的类型的命名空间,在所有元素名称前加上一个前缀。

<A xmlns:ns1="www.example.com">
    <ns1:B foo="123">
        <ns1:C>thing</ns1:C>
        <ns1:D>stuff</ns1:D>
    </ns1:B>
</A>

有没有办法使用lxml.etree或类似的库来执行此操作(除了强力查找替换或正则表达式)?

3 个答案:

答案 0 :(得分:2)

我不认为这可以通过ElementTree来完成。

操作命名空间有时候会非常棘手。这里有很多关于它的问题。即使使用更高级的lxml库,也可能非常困难。请参阅以下相关问题:

以下是使用XSLT的解决方案。

代码:

from lxml import etree

XML = '''
<A>
    <B foo="123">
        <C>thing</C>
        <D>stuff</D>
    </B>
</A>'''

XSLT = '''
<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ns1="www.example.com">
 <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="*">
   <xsl:element name="ns1:{name()}">
    <xsl:apply-templates select="node()|@*"/>
   </xsl:element>
  </xsl:template>

  <!-- No prefix on the A element -->
  <xsl:template match="A">
   <A xmlns:ns1="www.example.com">
    <xsl:apply-templates select="node()|@*"/>
   </A>
  </xsl:template>
</xsl:stylesheet>'''

xml_doc = etree.fromstring(XML)
xslt_doc = etree.fromstring(XSLT)
transform = etree.XSLT(xslt_doc)
print transform(xml_doc)

输出:

<A xmlns:ns1="www.example.com">
    <ns1:B foo="123">
        <ns1:C>thing</ns1:C>
        <ns1:D>stuff</ns1:D>
    </ns1:B>
</A>

答案 1 :(得分:0)

使用ET.register_namespace('ns1', 'www.example.com')向ElementTree注册名称空间。这是必需的,因此write()使用已注册的前缀。 (我的代码使用前缀''(空字符串)作为默认命名空间)

然后使用{www.example.com}为每个元素名称添加前缀。例如:root.find('{www.example.com}B')

答案 2 :(得分:0)

import xml.etree.ElementTree as ET

name_space = {
# namespace defined below
"xmlns:ns1":"www.example.com""="www.example.com"
}

A = ET.Element('A', name_space)
B = ET.SubElement(A, 'ns1:B')
C = ET.SubElement(B, 'ns1:C')
C.text = 'thing'

您可以将名称空间传递给Element构造函数,这时您可以在任何子组件处引用。请注意,您可以定义多个。这个解决方案对我有用。