lxml解析没有Schema URL的xsd文件

时间:2011-07-17 00:10:51

标签: python xml xsd lxml

我正在使用lxml来解析xsd文件,并且正在寻找一种简单的方法来删除附加到每个元素名称的URL命名空间。这是xsd文件:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="rootelement">
    <xs:complexType>
      <xs:choice maxOccurs="unbounded">
        <xs:element minOccurs="1" maxOccurs="1" name="element1">
          <xs:complexType>
            <xs:all>
              <xs:element name="subelement1" type="xs:string" />
              <xs:element name="subelement2" type="xs:integer" />
              <xs:element name="subelement3" type="xs:dateTime" />
            </xs:all>
            <xs:attribute name="id" type="xs:integer" use="required" />
          </xs:complexType>
        </xs:element>
       </xs:choice>
      <xs:attribute fixed="2.0" name="version" type="xs:decimal" use="required" />
    </xs:complexType>
  </xs:element>
</xs:schema>

并使用此代码:

from lxml import etree

parser = etree.XMLParser()
data = etree.parse(open("testschema.xsd"),parser)
root = data.getroot()
rootelement = root.getchildren()[0]
rootelementattribute = rootelement.getchildren()[0].getchildren()[1]
print "root element tags"
print rootelement[0].tag
print rootelementattribute.tag
elements = rootelement.getchildren()[0].getchildren()[0].getchildren()
elements_attribute = elements[0].getchildren()[0].getchildren()[1]
print "element tags"
print elements[0].tag
print elements_attribute.tag
subelements = elements[0].getchildren()[0].getchildren()[0].getchildren()
print "subelements"
print subelements

我得到以下输出

root element tags
{http://www.w3.org/2001/XMLSchema}complexType
{http://www.w3.org/2001/XMLSchema}attribute
element tags
{http://www.w3.org/2001/XMLSchema}element
{http://www.w3.org/2001/XMLSchema}attribute
subelements
[<Element {http://www.w3.org/2001/XMLSchema}element at 0x7f2998fb16e0>, <Element {http://www.w3.org/2001/XMLSchema}element at 0x7f2998fb1780>, <Element {http://www.w3.org/2001/XMLSchema}element at 0x7f2998fb17d0>]

当我拉取标签数据时,我不希望“{http://www.w3.org/2001/XMLSchema}”出现(更改xsd文件不是一个选项)。我需要xsd标记信息的原因是我使用它来验证一系列平面文件中的列名。在“元素”级别,我正在拉动多个元素,以及子元素,我使用字典来验证列。此外,任何有关改进上述代码的建议都会很大,例如使用较少的“getchildren”调用,或者只是让它更有条理。

4 个答案:

答案 0 :(得分:3)

我会用:

print elem.tag.split('}')[-1]

但您也可以使用xpath函数local-name()

print elem.xpath('local-name()')

对于较少getchildren()次来电:只是将它们排除在外。 getchildren()是一种不推荐使用的方式来制作直接子项列表(如果您真的需要,则应该使用list(elem))。

您可以迭代,或直接在元素上使用索引。例如:rootelement[0]会为您提供rootelement的第一个子元素(但比使用rootelement.getchildren()[0]更有效,因为这会像list(rootelement)一样创建一个新元素列表第一)

答案 1 :(得分:1)

我想知道为什么etree.XMLParser(ns_clean=True)不起作用。它对我没有用,所以它从括号中的root.nsmap获取命名空间并用空字符串

替换它
print rootelement[0].tag.replace('{%s}' %root.nsmap['xs'], '')

答案 2 :(得分:0)

最简单的方法是使用字符串切片来删除名称空间前缀:

>>> print rootelement[0].tag[34:]
complexType

答案 3 :(得分:0)

如果URI未来可能会发生变化(由于某些未知原因或您确实是偏执狂),请考虑以下事项:

print "root element tags"
tag, nsmap, prefix = rootelement[0].tag, rootelement[0].nsmap, rootelement[0].prefix
tag = tag[len(nsmap[prefix]) + 2:]
print tag

这是一个非常不可能的案例,但谁知道呢?