python sax xml名称的子标签

时间:2012-02-27 17:13:06

标签: python xml xml-parsing sax

我试图用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”?

1 个答案:

答案 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.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解析器更快,使用的内存更少,这在十年前非常重要,但现代处理器的差距要小得多,特别是在小型文档上。程序员的时间更有价值。