开发者

how to set a namespace prefix in an attribute value using the lxml?

开发者 https://www.devze.com 2023-01-16 04:05 出处:网络
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=\"qualifi

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?


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:

  • add your nsmap with the 'xs' prefix to every element you create; or
  • use the _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.

0

精彩评论

暂无评论...
验证码 换一张
取 消