假设我有一个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
或类似的库来执行此操作(除了强力查找替换或正则表达式)?
答案 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构造函数,这时您可以在任何子组件处引用。请注意,您可以定义多个。这个解决方案对我有用。