【问题标题】:Text between tag using SAX parser in Python在 Python 中使用 SAX 解析器的标签之间的文本
【发布时间】:2021-12-14 17:24:34
【问题描述】:

我想使用 SAX 打印 XML 文件中特定标记之间的文本。

但是,某些文本输出包含空格或换行符。

有没有办法只挑出实际的字符串?我做错了什么?

请参阅下面的代码提取和 XML 文档。

(我在 Python 2 和 Python 3 中都获得了相同的效果。)

#!/usr/bin/env python3

import xml.sax

class MyHandler(xml.sax.ContentHandler):

        def startElement(self, name, attrs):
                self.tag = name

        def characters(self, content):
                if self.tag == "artist":
                        print('[%s]' % content)

if __name__=='__main__':
        parser=xml.sax.make_parser()
        Handler=MyHandler()
        parser.setContentHandler(Handler) #overriding default ContextHandler
        parser.parse("songs.xml")
<?xml version="1.0"?>
<genre catalogue="Pop">
  <song title="No Tears Left to Cry">
    <artist>Ariana Grande</artist>
    <year>2018</year>
    <album>Sweetener</album>
  </song>
  <song title="Delicate">
    <artist>Taylor Swift</artist>
    <year>2018</year>
    <album>Reputation</album>
  </song>
  <song title="Mrs. Potato Head">
    <artist>Melanie Martinez</artist>
    <year>2015</year>
    <album>Cry Baby</album>
  </song>
</genre>

【问题讨论】:

  • ok 澄清了措辞,进行了编辑以包含完整的最小示例代码并添加了 XML 文档。
  • 另一个问题是 pylint 抱怨标签是在 init 之外定义的(代码 W0201),但是,如果我在类中添加一个 init 方法, pylint 抱怨这个方法不是从基类调用的(代码 W0231),

标签: python python-3.x xml python-2.x sax


【解决方案1】:

self.tag 的值在遇到 &lt;artist&gt; 开始标记时设置为“艺术家”,并且在为 &lt;year&gt; 开始标记调用 startElement() 之前不会更改。在这些元素之间是一些无趣的空白,解析器也会报告 SAX 事件。

解决此问题的一种方法是将endElement() 方法添加到MyHandler,将self.tag 设置为其他值。

def endElement(self, name):
    self.tag = "whatever"

【讨论】:

    【解决方案2】:

    如果您想使用 SAX,那么您需要对 XML 规范有深入的了解。空白的技术名称是“混合内容”。它出现在第一个子标签之前、子标签之间和最后一个子标签之后。大多数 XML 处理器将报告混合内容的 SAX 事件。有些有一个禁止它的标志(因为许多应用程序只对纯文本内容或纯元素内容感兴趣)。

    解决方案包括:

    a) 停止使用 SAX。 DOM 会更直接

    b) 添加代码以检测您感兴趣的标签的 startElement 和 endElement 事件。忽略事件,除非您位于“有趣”标签之一内。

    c) 使用 XSLT 将您的 XML 文档转换为您需要的任何形式(请参阅How to transform an XML file using XSLT in Python?

    我的选择永远是 c),因为 XSLT 是一个超级大国,它让这类任务变得非常简单。

    【讨论】:

    • 嗨@kimbert,感谢您的回答。假设使用 SAX,除了将代码修改为 if self.tag == "parameterName" and content[0] != '\n' and content[0] != ' ': names.append(content) 之外,是否有针对此问题的特定修复?
    • 总是有不止一种方法可以做到这一点:-)。如果您只关心一个标签名称,您的解决方案将有效。但我认为你不需要测试 '\n' 和 ' ',除非你想在 'parameterName' 标记的第一个字符中抑制前导空格。
    猜你喜欢
    • 2018-01-24
    • 1970-01-01
    • 2011-02-19
    • 2013-07-02
    • 2012-11-16
    • 2012-11-10
    • 2013-01-08
    • 2012-05-26
    相关资源
    最近更新 更多