thing stuff ...">

How to insert namespace and prefixes into XML string using Python?

Suppose I have an XML string:

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

      

and I want to insert a namespace of the type used in the XML schema by putting a prefix in front of all element names.

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

      

Is there a way to do this (other than brute force find-replace or regex) using lxml.etree

or a similar library?

+3


source to share


2 answers


I don't think it can only be done with ElementTree.

Manipulating namespaces is sometimes surprisingly difficult. There are many questions about this. Even with the more advanced lxml library it can be very tricky. See the following questions:

Below is a solution using XSLT.



code:

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)

      

Output:

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

      

+2


source


Use ET.register_namespace('ns1', 'www.example.com')

to register namespaces with ElementTree. This is required, so it write()

uses the registered prefix. (I have some code that uses a prefix ''

(empty string) for the default namespace)



Then prefix each element name {www.example.com}

. For example: root.find('{www.example.com}B')

.

0


source







All Articles