2010-09-10 60 views
3

我正在尝试使用lxml创建XML模式。对于的游戏内是这样的:如何使用lxml在属性值中设置命名空间前缀?

<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> 

我已经做到了这种方式 - 通过putthing XS:前值,但我认为这是可以做到更好。

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) 

它可以以某种方式写得更好吗?

回答

2

有点值得一提,你需要在你的NSMAP中包含"xs": SCHEMA_NAMESPACE等,否则在你生成的XML中没有任何东西实际将'xs'前缀映射到正确的名称空间。这也可以让你只用前缀指定你的元素名称;例如“XS:元素”。

至于你的主要问题,我认为这可能很好,只要你总是在任何地方使用相同的前缀到名称空间映射,比如全局的NSMAP。如果你正在处理XML具有潜在的任意命名空间前缀,然后确保要么:

  • 与“XS”前缀创建的每一个元素添加您的nsmap;或
  • 使用_Element.nsmap属性获取父属性的名称空间映射,将其反转,并在倒转映射中查找适当的前缀。

后者的一个例子:

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) 

但是,这可能是大多数情况下矫枉过正。