lxml 无需 Schema URL 解析 xsd 文件
我正在使用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
最简单的方法就是用字符串切片来去掉命名空间前缀:
>>> print rootelement[0].tag[34:]
complexType
1
我想知道为什么 etree.XMLParser(ns_clean=True)
不好使。对我来说,它一直都没用,似乎是因为它从根节点的命名空间映射中获取了内容,然后把它替换成了空字符串。
print rootelement[0].tag.replace('{%s}' %root.nsmap['xs'], '')
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)
一样创建一个新列表)。