Reputation: 2334
I'm trying to create XML Schema using lxml. For the begining something like this:
<xs:schema xmlns="http://www.goo.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.goo.com">
<xs:element type="xs:string" name="name"/>
<xs:element type="xs:positiveInteger" name="age"/>
</xs:schema>
I've done it this way - by putthing xs: before value, but I think it could be done better.
def schema():
SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema"
XS = "{%s}" % SCHEMA_NAMESPACE
NSMAP = {None: "http://www.goo.com"}
schema = etree.Element(XS+"schema",
nsmap = NSMAP,
targetNamespace="http://www.goo.com",
elementFormDefault="qualified")
element = etree.Element(XS+"element",
attrib = {"name" : "name",
"type" : "xs:string"})
schema.append(element)
element = etree.Element(XS+"element",
attrib = {"name" : "age",
"type" : "xs:positiveInteger"})
schema.append(element)
return etree.tostring(schema, pretty_print=True)
Can it be written somehow better?
Upvotes: 3
Views: 4238
Reputation: 4485
Somewhat as an aside, you need to include "xs": SCHEMA_NAMESPACE
or such in your NSMAP -- otherwise nothing in your generated XML actually maps the 'xs' prefix to correct namespace. That will also allow you to just specify your element names with prefixes; e.g. "xs:element".
As far as your main question, I think this is probably fine, as long as you always use the same prefix-to-namespace mapping everywhere, such as with a global NSMAP
. If you're processing XML with potentially arbitrary namespace prefixes, then make sure to either:
nsmap
with the 'xs' prefix to every element you create; or_Element.nsmap
attribute to get the namespace map of the parent attribute, invert it, and look up the appropriate prefix in the inverted map.An example of the latter:
SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema"
def add_element(schema):
nsmap = schema.nsmap
nsrmap = dict([(uri, prefix) for prefix, uri in nsmap.items()])
prefix = nsrmap[SCHEMA_NAMESPACE]
xs = lambda name: "%s:%s" % (prefix, name)
element = schema.makeelement(xs("element"), nsmap=nsmap,
attrib={'name': 'age', 'type': xs('string')})
schema.append(element)
return etree.tostring(schema, pretty_print=True)
But that's probably overkill for most cases.
Upvotes: 2