Reputation: 593
Thanks to this question/answer, I was able to get a namespace attribute added to a root element. So now I have this:
Code
from lxml.builder import ElementMaker
foo = 'http://www.foo.org/XMLSchema/bar'
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
E = ElementMaker(namespace=foo, nsmap={'foo': foo, 'xsi': xsi})
fooroot = E.component()
fooroot.attrib['{{{pre}}}schemaLocation'.format(pre=xsi)] = 'http://www.foo.org/XMLSchema/bar http://www.foo.org/XMLSchema/barindex.xsd'
bars = E.bars(label='why?', validates='required')
fooroot.append(bars)
bars.append(E.bar(label='Image1'))
bars.append(E.bar(label='Image2'))
etree.dump(fooroot)
This give me the desired output:
Output
<foo:component xmlns:foo="http://www.foo.org/XMLSchema/bar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.foo.org/XMLSchema/bar http://www.foo.org/XMLSchema/barindex.xsd">
<foo:bars label="why?" validates="required">
<foo:bar label="Image1"/>
<foo:bar label="Image2"/>
</foo:bars>
</foo:component>
The question
Why does the fooroot.attrib['{{{pre}}}schemaLocation'.format(pre=xsi)]
require 3 braces around the pre?
1 brace: {pre}
causes a ValueError BAD
2 braces: {{pre}}
produces ns0:schemaLocation
on the output BAD
3 braces: {{{pre}}}
produces xsi:schemaLocation
on the output GOOD
I understand the .format
usage for the string, but I'd like to understand why I need 3 braces.
Upvotes: 3
Views: 1652
Reputation: 89285
The format of namespaced attribute name in lxml
is {namespace-uri}local-name
. So for xsi:schemaLocation
, you basically want to add attribute with name:
'{http://www.w3.org/2001/XMLSchema-instance}schemaLocation'
The {namespace-uri}
part can be achieved using format()
and the triple opening and closing braces which can be read as:
{{
: escaped opening braces; outputs literal {
{pre}
: placeholder; will be replaced by the value of variable xsi
as specified in .format(pre=xsi)
}}
: escaped closing braces; outputs literal }
Upvotes: 5