Namespace inconsistency with attributes

Hello! I have a problem with namespaces for attributes. lxml takes always first value (which in my case is default) from list of namespaces and uses it for attributes. My xml file: <Root xmlns="urn:schemas-microsoft- com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Child ss:Color = "Blue"/> </Root> My program which adds one child element: from lxml import etree from StringIO import StringIO f = StringIO('<Root xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"><Child ss:Color = "Blue"/></Root>') parser = etree.parse(f) nameSpaces = {'ss': 'urn:schemas-microsoft-com:office:spreadsheet'} nameSpace = '{urn:schemas-microsoft-com:office:spreadsheet}' root = parser.xpath("/ss:Root", namespaces = nameSpaces)[0] child = etree.Element("Child") child.set(nameSpace+"Color","Red") root.append(child) print etree.tostring(root, pretty_print=True) And my result: <Root xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Child ss:Color="Blue"/> <Child Color="Red"/> </Root> I would like to have: <Root xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Child ss:Color="Blue"/> <Child ss:Color="Red"/> </Root> If i changed position of default namespace (I will put it at the end) everything will be OK. I will get attribute with prefix ss. But I cannot do this in that way. Is there other way to handle with that problem? Thanks in advance Bartek

Hi,
<Root xmlns="urn:schemas-microsoft- com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Child ss:Color = "Blue"/> </Root>
Note that the same "namespace urn:schemas-microsoft-com:office:spreadsheet" is declared for both unprefixed nodes and for nodes prefixed with "ss:" here. In other words both unprefixed and ss-prefixed nodes live in that namespace.
And my result:
<Root xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Child ss:Color="Blue"/> <Child Color="Red"/> </Root>
I would like to have:
<Root xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Child ss:Color="Blue"/> <Child ss:Color="Red"/> </Root>
Well, from an XML-processing point of view those are equivalent:
root.xpath('//@ss:*', namespaces={'ss': 'urn:schemas-microsoft-com:office:spreadsheet'}) ['Blue', 'Red']
So maybe this isn't really a problem apart from cosmetics? I don't know of a way to control this behaviour. Looks to me that append()ing the element caters for namespace-map consistency and chooses to use the unprefixed variant for some reason (might be that Element.nsmap is ordered internally and so the non-prefix entry is found first):
root = etree.fromstring("""<Root xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"><Child ss:Color = "Blue"/></Root>""") nameSpace = 'urn:schemas-microsoft-com:office:spreadsheet' nameSpaces = {None: nameSpace, 'ss': nameSpace} child = etree.Element("Child", nsmap=nameSpaces) child.set("{%s}%s" % (nameSpace, "Color"),"Red") # # Here the intended prefix is still in use print etree.tostring(child, pretty_print=True) <Child xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns="urn:schemas-microsoft-com:office:spreadsheet" ss:Color="Red"/>
root.append(child) # # Now the internal nsmap handling has done its deeds print etree.tostring(root, pretty_print=True) <Root xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Child ss:Color="Blue"/> <Child Color="Red"/> </Root>
Holger -- Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de

<jholg <at> gmx.de> writes:
And my result:
<Root xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Child ss:Color="Blue"/> <Child Color="Red"/> </Root>
I would like to have:
<Root xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Child ss:Color="Blue"/> <Child ss:Color="Red"/> </Root>
Well, from an XML-processing point of view those are equivalent:
root.xpath('//@ss:*', namespaces={'ss':
'urn:schemas-microsoft-com:office:spreadsheet'})
['Blue', 'Red']
So maybe this isn't really a problem apart from cosmetics?
In fact for me it is really important. XML file which doesn't contain 'ss' in front of attribute cannot be read by MS Office Excel. Maybe I can "somehow" changed order in nsmap of root element? Thanks in advance for any clues Bartek
participants (3)
-
Bartek
-
Bartek Urbaniec
-
jholg@gmx.de