python-sax-xml子标记的名称



我正在尝试使用python的sax库获取children标记的名称。我使用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"one_answers"child2"?

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.minidomlxml)更容易用于这类任务,因为它可以为您跟踪元素之间的关系。这样的解析器可能是满足您需求的更好选择:

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解析器更快,占用的内存更少,但在现代处理器上,尤其是在小文档上,差距要小得多。程序员的时间更有价值。

最新更新