我试图用python的sax库获取子标签的名称。我使用ContentHandler作为处理程序。任何人都知道如何获取标签名称?
我们假设我们的xml文档如下:
<root>
<parent>
<child1>X</child1>
<child2>Y</child2>
</parent>
</root>
让我们假设我们使用模板作为处理程序:
class parserSAXHandler(handler.ContentHandler):
def __init__(self):
pass;
def startElement(self, name, attrs):
pass;
def endElement(self,name):
pass;
def characters(self, content):
pass;
如果我只知道父母的名字,我怎样才能获得字符串“child1”和“child2”?
答案 0 :(得分:6)
SAX风格的解析器要求您跟踪所需的所有状态,例如您看到的标签。最重要的是,你需要做的是编写一个startElement()
处理程序,当它看到<parent>
标记时设置一个标记,而endElement()
在看到结束标记时清除该标记。当设置此标志时,startElement()
处理程序还需要累积它在列表中看到的标记。
class parserSAXHandler(handler.ContentHandler):
def __init__(self):
self.parentflag = False
self.childlist = []
def startElement(self, name, attrs):
if name == "parent":
self.parentflag = True
elif self.parentflag:
self.childlist.append(name)
def endElement(self,name):
if name == "parent":
self.parentflag = False
解析后,实例的childlist
属性将包含您想要的列表。
如果可以将其他标记嵌套在<child>
标记内并且不想要这些标记名称,则可能需要更复杂的逻辑。实际上,包含嵌套在任何级别的<parent>
容器内的任何标记。跟踪嵌套的最简单方法可能是堆栈:按下每个开始标记,弹出每个结束标记,然后您可以检查parent
是否位于堆栈顶部。
class parserSAXHandler(handler.ContentHandler):
def __init__(self):
self.tagstack = []
self.childlist = []
def startElement(self, name, attrs):
if self.tagstack[-1] == "parent":
self.childlist.append(name)
self.tagstack.append(name)
def endElement(self,name):
if name == self.tagstack[-1]:
self.tagstack.pop()
else:
raise SAXParseException("tag closed without being open")
DOM样式的解析器(例如xml.dom.minidom
或lxml
)可以更轻松地处理这些类型的任务,因为它可以为您跟踪元素之间的关系。这样的解析器可能是您需求的更好选择:
from xml.dom.minidom import parseString
xml = """
<root>
<parent>
<child1>X</child1>
<child2>Y</child2>
</parent>
</root>
"""
dom = parseString(xml)
children = [c.localName for p in dom.getElementsByTagName("parent")
for c in p.childNodes if c.nodeType == c.ELEMENT_NODE]
您会注意到,一旦minidom
模块解析了我们的XML,您的查询就是单个Python语句(当然,它包含两个循环,但它仍然只是一个语句)。使用SAX风格的解析器无法真正达到这种简洁程度。
现在,SAX风格的解析器比DOM解析器更快,使用的内存更少,这在十年前非常重要,但现代处理器的差距要小得多,特别是在小型文档上。程序员的时间更有价值。