Python 中的 SAX 是否有一个索引告诉我我在 XML 文件中的位置?我怎么会发现呢?

Does SAX in Python have an index that tells me where I am in an XML file? And how would I find that out?

我有一个具体问题和一个一般问题。

假设我正在使用 SAX 来处理下面的 XML,但它实际上有 17MB 并且复杂得多。代码没有错误,但因为它太复杂了,我可能一开始就不应该接近 SAX,我遇到了一个令人沮丧的逻辑错误——它有时会输出一个我不感兴趣的值,有时正确地忽略它。这个逻辑错误是唯一阻止我完成项目的原因。我正在尝试调试代码,但这非常令人沮丧,因为即使我的截断测试 XML 文件也有 42,000 行。

所以我的具体问题是如何查看 XML 文件的哪一行触发了任何给定的 startElement。 startElement 或 ContentHandler 是否有索引或其他东西告诉您它在文件中的位置?

我的一般问题是我怎样才能找到自己做这件事的方法?我可以在 Google 上四处游荡,Stack Overflow 是一个我非常感激的巨大资源,但如果我可以独立调查我正在使用的东西的属性,那会更令人满意。例如,有没有办法,在我的代码中,我可以得到一个列表,列出所有挂在 startElement 或变量或任何东西上的东西,真的。 Len() 告诉我某物有多长,Type() 告诉我它是什么类型。当我不确定我遇到的问题 种类 时,是否还有其他有用的元命令可以求助?

我有点预料到会因为一个问题问两个问题而被骂,但我知道如何提出一般性问题而不会因为太模糊而被骂。

此代码归功于 http://pyxml.sourceforge.net/topics/howto/node12.html

<collection>
  <comic title="Sandman" number='62'>
    <writer>Neil Gaiman</writer>
    <penciller pages='1-9,18-24'>Glyn Dillon</penciller>
    <penciller pages="10-17">Charles Vess</penciller>
  </comic>
</collection>

我用下面的代码处理XML:

from xml.sax import saxutils

class FindIssue(saxutils.handler.ContentHandler):
    def __init__(self, title, number):
        self.search_title, self.search_number = title, number

    def startElement(self, name, attrs):
        # If it's not a comic element, ignore it
        if name != 'comic': return

        # Look for the title and number attributes (see text)
        title = attrs.get('title', None)
        number = attrs.get('number', None)
        if (title == self.search_title and number == self.search_number):
            print (title, '#' + str(number), 'found')
            
from xml.sax import make_parser
from xml.sax.handler import feature_namespaces

if __name__ == '__main__':
    # Create a parser
    parser = make_parser()

    # Tell the parser we are not interested in XML namespaces
    parser.setFeature(feature_namespaces, 0)

    # Create the handler
    dh = FindIssue('Sandman', '62')

    # Tell the parser to use our handler
    parser.setContentHandler(dh)

    # Parse the input
    parser.parse("test.xml")

这是您的示例的一个版本,它还打印匹配元素的行和列。

import io
from xml.sax import saxutils
from xml.sax import make_parser
from xml.sax.handler import feature_namespaces


class FindIssue(saxutils.handler.ContentHandler):
    def __init__(self, title, number):
        self.locator = None
        self.search_title = title
        self.search_number = number

    def setDocumentLocator(self, loc):
        self.locator = loc

    def startElement(self, name, attrs):
        if name != "comic":
            return
        title = attrs.get("title")
        number = attrs.get("number")
        if title == self.search_title and number == self.search_number:
            if self.locator:
                print("Line", self.locator.getLineNumber(), "column", self.locator.getColumnNumber())
            print(title, "#" + str(number), "found")


# Create a parser
parser = make_parser()
parser.setFeature(feature_namespaces, 0)

issue_finder = FindIssue("Sandman", "62")
parser.setContentHandler(issue_finder)
parser.parse(
    io.StringIO(
        """
<collection>
<comic title="Sandman" number='62'>
<writer>Neil Gaiman</writer>
<penciller pages='1-9,18-24'>Glyn Dillon</penciller>
<penciller pages="10-17">Charles Vess</penciller>
</comic>
</collection>
""".strip()
    )
)