3

假设我有一个 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有没有办法使用或类似的库来做到这一点(除了蛮力查找替换或正则表达式) ?

4

3 回答 3

4

我认为这不能仅用 ElementTree 来完成。

操作命名空间有时非常棘手。SO上有很多关于它的问题。即使使用更高级的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>
于 2015-08-07T05:23:10.830 回答
1
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 构造函数,此时您可以在任何子组件处引用。请注意,您可以定义多个。这个解决方案对我有用。

于 2020-01-21T23:35:22.120 回答
0

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

然后在每个元素名称前加上{www.example.com}. 例如: root.find('{www.example.com}B')

于 2015-08-06T19:56:28.417 回答