Title

python 使用sax 解析xml 文件

————转自(12条消息) python 使用sax 解析xml 文件_小牧在一直在学习,在前进的道路上大家一起学习,进步。-CSDN博客

SAX知识了解

SAX (simple API for XML )  有解析器和事件处理器

解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件。

而事件处理器则负责对事件作出响应,对传递的XML数据进行处理。

sax的主要方法

1 startDocument() : 文档启动的时候调用。

2 endDocument() : 解析器到达文档结尾时调用。

3 startElement(name, attrs): 遇到XML开始标签时调用,name是标签的名字,attrs是标签的属性值字典。

4 endElement(name) : 遇到XML结束标签时调用。

5 characters :内容处理

6 make_parser : 创建一个解释器对象并返回

7 parser : 解析xml

demo 练习 python的 sax 解析xml

demo1 读取只有标签的xml

创建一个config.xml 的文件内容如下:

  1.  
    <?xml version="1.0" encoding="UTF-8"?>
  2.  
    <config_content>
  3.  
    <lib name="a" path="a的路径"/>
  4.  
    <lib name="b" path="b的路径"/>
  5.  
    <lib name="c" path="c的路径"/>
  6.  
    </config_content>

代码如下

  1.  
    import xml.sax
  2.  
     
  3.  
     
  4.  
    class ConfigHandler(xml.sax.ContentHandler):
  5.  
     
  6.  
    def __init__(self):
  7.  
    self.tag = ""
  8.  
    self.name = ""
  9.  
    self.path = ""
  10.  
     
  11.  
    # 启动文档
  12.  
    def startDocument(self):
  13.  
    print("******解析配置文件开始******")
  14.  
     
  15.  
    # 开始解析xml
  16.  
    def startElement(self, name, attributes):
  17.  
    self.tag = name
  18.  
    if name == "lib":
  19.  
    self.name = attributes["name"]
  20.  
    self.path = attributes["path"]
  21.  
    print(self.name)
  22.  
    print(self.path)
  23.  
     
  24.  
    # xml内容事件处理
  25.  
    def characters(self, content):
  26.  
    pass
  27.  
     
  28.  
    # 结束解析xml
  29.  
    def endElement(self, name):
  30.  
    pass
  31.  
     
  32.  
    # xml结束标签调用
  33.  
    def endDocument(self):
  34.  
    print("******配置文件解析结束******")
  35.  
     
  36.  
     
  37.  
    if __name__ == "__main__":
  38.  
    # 创建一个 XMLReader
  39.  
    parser = xml.sax.make_parser()
  40.  
    # turn off namepsaces
  41.  
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
  42.  
    # 重写 ContextHandler
  43.  
    Handler = ConfigHandler()
  44.  
    parser.setContentHandler(Handler)
  45.  
    # 解析 xml 这里可以写xml 的具体路径,为了简单放在了同一个文件夹里面了
  46.  
    parser.parse("config.xml")

打印结果如下

由于读取的xml 只有标签这里内容处理和结束的时候并没有做其他的操作,可以出sax 读取xml 的时候是一行一行读取的,这里只有单行所以没有重复的问题,如果我们要使用读取的数据,可以把数据存放到 list 中或者存放到字典中,如下

  1.  
    class ConfigHandler(xml.sax.ContentHandler):
  2.  
    config_map = {}
  3.  
    config_name_list = []
  4.  
    config_path_list = []
  5.  
     
  6.  
    def __init__(self):
  7.  
    self.tag = ""
  8.  
    self.name = ""
  9.  
    self.path = ""
  10.  
     
  11.  
    # 启动文档
  12.  
    def startDocument(self):
  13.  
    print("******解析配置文件开始******")
  14.  
     
  15.  
    # 开始解析xml
  16.  
    def startElement(self, name, attributes):
  17.  
    self.tag = name
  18.  
    if name == "lib":
  19.  
    self.name = attributes["name"]
  20.  
    self.path = attributes["path"]
  21.  
    # print(self.name)
  22.  
    # print(self.path)
  23.  
    self.config_name_list.append(self.name)
  24.  
    print(self.config_name_list)
  25.  
    self.config_path_list.append(self.path)
  26.  
    print(self.config_path_list)
  27.  
    self.config_map.update({self.name: self.path})
  28.  
    print(self.config_map)
  29.  
     
  30.  
    # xml内容事件处理
  31.  
    def characters(self, content):
  32.  
    pass
  33.  
     
  34.  
    # 结束解析xml
  35.  
    def endElement(self, name):
  36.  
    pass
  37.  
    # xml结束标签调用
  38.  
    def endDocument(self):
  39.  
    print("******配置文件解析结束******")
  40.  
     
  41.  
     
  42.  
    if __name__ == "__main__":
  43.  
    # 创建一个 XMLReader
  44.  
    parser = xml.sax.make_parser()
  45.  
    # turn off namepsaces
  46.  
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
  47.  
    # 重写 ContextHandler
  48.  
    Handler = ConfigHandler()
  49.  
    parser.setContentHandler(Handler)
  50.  
    # 解析 xml 这里可以写xml 的具体路径,为了简单放在了同一个文件夹里面了
  51.  
    parser.parse("config.xml")

打印结果

demo2 读取同标签不同内容的xml

xml内容如下

  1.  
    <?xml version="1.0" encoding="UTF-8"?>
  2.  
    <config_content>
  3.  
    <type class="3年级">
  4.  
    <lib name="体育">优秀</lib>
  5.  
    <lib name="语文">一般</lib>
  6.  
    <lib name="数学">优秀</lib>
  7.  
    </type>
  8.  
    <type class="5年级">
  9.  
    <lib name="体育">一般</lib>
  10.  
    <lib name="语文">优秀</lib>
  11.  
    <lib name="数学">良好</lib>
  12.  
    </type>
  13.  
    </config_content>

python 代码如下

  1.  
    import xml.sax
  2.  
     
  3.  
     
  4.  
    class ConfigHandler(xml.sax.ContentHandler):
  5.  
     
  6.  
    def __init__(self):
  7.  
    self.tag = ""
  8.  
    self.name = ""
  9.  
    self.label = ""
  10.  
    self.content = ""
  11.  
     
  12.  
    # 启动文档
  13.  
    def startDocument(self):
  14.  
    print("******解析配置文件开始******")
  15.  
     
  16.  
    # 开始解析xml
  17.  
    def startElement(self, name, attributes):
  18.  
    self.tag = name
  19.  
    if name == "type":
  20.  
    self.name = attributes["class"]
  21.  
    print(self.name)
  22.  
    if name == "lib":
  23.  
    self.label = attributes["name"]
  24.  
    print(self.label)
  25.  
     
  26.  
    # xml内容事件处理
  27.  
    def characters(self, content):
  28.  
    self.content = content
  29.  
     
  30.  
    # 结束解析xml
  31.  
    def endElement(self, name):
  32.  
    if name == "lib":
  33.  
    print(self.content)
  34.  
     
  35.  
    # xml结束标签调用
  36.  
    def endDocument(self):
  37.  
    print("******配置文件解析结束******")
  38.  
     
  39.  
     
  40.  
    if __name__ == "__main__":
  41.  
    # 创建一个 XMLReader
  42.  
    parser = xml.sax.make_parser()
  43.  
    # turn off namepsaces
  44.  
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
  45.  
    # 重写 ContextHandler
  46.  
    Handler = ConfigHandler()
  47.  
    parser.setContentHandler(Handler)
  48.  
    # 解析 xml 这里可以写xml 的具体路径,为了简单放在了同一个文件夹里面了
  49.  
    parser.parse("config.xml")

打印结果如下


demo3 读取相同标签多个标题的xml

xml 内容如下

  1.  
    <?xml version="1.0" encoding="UTF-8"?>
  2.  
    <config_content>
  3.  
    <school name="第六中学">
  4.  
    <type class="2年级">
  5.  
    <Language>优秀</Language>
  6.  
    <Math>一般</Math>
  7.  
    <English>优秀</English>
  8.  
    </type>
  9.  
    <type class="5年级">
  10.  
    <Language>优秀</Language>
  11.  
    <Math>一般</Math>
  12.  
    <English>优秀</English>
  13.  
    </type>
  14.  
    </school>
  15.  
    <school name="第九中学">
  16.  
    <type class="1年级">
  17.  
    <Language>优秀</Language>
  18.  
    <Math>一般</Math>
  19.  
    <English>优秀</English>
  20.  
    </type>
  21.  
    <type class="3年级">
  22.  
    <Language>优秀</Language>
  23.  
    <Math>一般</Math>
  24.  
    <English>优秀</English>
  25.  
    </type>
  26.  
    </school>
  27.  
    </config_content>

python 代码如下

  1.  
    import xml.sax
  2.  
     
  3.  
     
  4.  
    class ConfigHandler(xml.sax.ContentHandler):
  5.  
     
  6.  
    def __init__(self):
  7.  
    self.tag = ""
  8.  
    self.name = ""
  9.  
    self.label = ""
  10.  
    self.content = ""
  11.  
     
  12.  
    # 启动文档
  13.  
    def startDocument(self):
  14.  
    print("******解析配置文件开始******")
  15.  
     
  16.  
    # 开始解析xml
  17.  
    def startElement(self, name, attributes):
  18.  
    self.tag = name
  19.  
    if name == "school":
  20.  
    self.name = attributes["name"]
  21.  
    print(self.name)
  22.  
    if name == "type":
  23.  
    self.label = attributes["class"]
  24.  
    print(self.label)
  25.  
     
  26.  
    # xml内容事件处理
  27.  
    def characters(self, content):
  28.  
    self.content = content
  29.  
     
  30.  
    # 结束解析xml
  31.  
    def endElement(self, name):
  32.  
    if name == "Language":
  33.  
    print(self.content)
  34.  
    elif name == "Math":
  35.  
    print(self.content)
  36.  
    elif name == "English":
  37.  
    print(self.content)
  38.  
     
  39.  
    # xml结束标签调用
  40.  
    def endDocument(self):
  41.  
    print("******配置文件解析结束******")
  42.  
     
  43.  
     
  44.  
    if __name__ == "__main__":
  45.  
    # 创建一个 XMLReader
  46.  
    parser = xml.sax.make_parser()
  47.  
    # turn off namepsaces
  48.  
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
  49.  
    # 重写 ContextHandler
  50.  
    Handler = ConfigHandler()
  51.  
    parser.setContentHandler(Handler)
  52.  
    # 解析 xml 这里可以写xml 的具体路径,为了简单放在了同一个文件夹里面了
  53.  
    parser.parse("config.xml")

打印结果如下:

******解析配置文件开始******
第六中学
2年级
优秀
一般
优秀
5年级
优秀
一般
优秀
第九中学
1年级
优秀
一般
优秀
3年级
优秀
一般
优秀
******配置文件解析结束******

最后总结,python 使用sax 读取xml 不难,可能存在组合数据的时候出现数据重现的问题,这个可以在拼接完数据之后,清空一下数据源,试试看,由于需求不一样,这里就不在写各种需求的组合数据了,大家注意一下数据重复问题即可。

SAX知识了解

SAX (simple API for XML )  有解析器和事件处理器

解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件。

而事件处理器则负责对事件作出响应,对传递的XML数据进行处理。

sax的主要方法

1 startDocument() : 文档启动的时候调用。

2 endDocument() : 解析器到达文档结尾时调用。

3 startElement(name, attrs): 遇到XML开始标签时调用,name是标签的名字,attrs是标签的属性值字典。

4 endElement(name) : 遇到XML结束标签时调用。

5 characters :内容处理

6 make_parser : 创建一个解释器对象并返回

7 parser : 解析xml

demo 练习 python的 sax 解析xml

demo1 读取只有标签的xml

创建一个config.xml 的文件内容如下:

  1.  
    <?xml version="1.0" encoding="UTF-8"?>
  2.  
    <config_content>
  3.  
    <lib name="a" path="a的路径"/>
  4.  
    <lib name="b" path="b的路径"/>
  5.  
    <lib name="c" path="c的路径"/>
  6.  
    </config_content>

代码如下

  1.  
    import xml.sax
  2.  
     
  3.  
     
  4.  
    class ConfigHandler(xml.sax.ContentHandler):
  5.  
     
  6.  
    def __init__(self):
  7.  
    self.tag = ""
  8.  
    self.name = ""
  9.  
    self.path = ""
  10.  
     
  11.  
    # 启动文档
  12.  
    def startDocument(self):
  13.  
    print("******解析配置文件开始******")
  14.  
     
  15.  
    # 开始解析xml
  16.  
    def startElement(self, name, attributes):
  17.  
    self.tag = name
  18.  
    if name == "lib":
  19.  
    self.name = attributes["name"]
  20.  
    self.path = attributes["path"]
  21.  
    print(self.name)
  22.  
    print(self.path)
  23.  
     
  24.  
    # xml内容事件处理
  25.  
    def characters(self, content):
  26.  
    pass
  27.  
     
  28.  
    # 结束解析xml
  29.  
    def endElement(self, name):
  30.  
    pass
  31.  
     
  32.  
    # xml结束标签调用
  33.  
    def endDocument(self):
  34.  
    print("******配置文件解析结束******")
  35.  
     
  36.  
     
  37.  
    if __name__ == "__main__":
  38.  
    # 创建一个 XMLReader
  39.  
    parser = xml.sax.make_parser()
  40.  
    # turn off namepsaces
  41.  
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
  42.  
    # 重写 ContextHandler
  43.  
    Handler = ConfigHandler()
  44.  
    parser.setContentHandler(Handler)
  45.  
    # 解析 xml 这里可以写xml 的具体路径,为了简单放在了同一个文件夹里面了
  46.  
    parser.parse("config.xml")

打印结果如下

由于读取的xml 只有标签这里内容处理和结束的时候并没有做其他的操作,可以出sax 读取xml 的时候是一行一行读取的,这里只有单行所以没有重复的问题,如果我们要使用读取的数据,可以把数据存放到 list 中或者存放到字典中,如下

  1.  
    class ConfigHandler(xml.sax.ContentHandler):
  2.  
    config_map = {}
  3.  
    config_name_list = []
  4.  
    config_path_list = []
  5.  
     
  6.  
    def __init__(self):
  7.  
    self.tag = ""
  8.  
    self.name = ""
  9.  
    self.path = ""
  10.  
     
  11.  
    # 启动文档
  12.  
    def startDocument(self):
  13.  
    print("******解析配置文件开始******")
  14.  
     
  15.  
    # 开始解析xml
  16.  
    def startElement(self, name, attributes):
  17.  
    self.tag = name
  18.  
    if name == "lib":
  19.  
    self.name = attributes["name"]
  20.  
    self.path = attributes["path"]
  21.  
    # print(self.name)
  22.  
    # print(self.path)
  23.  
    self.config_name_list.append(self.name)
  24.  
    print(self.config_name_list)
  25.  
    self.config_path_list.append(self.path)
  26.  
    print(self.config_path_list)
  27.  
    self.config_map.update({self.name: self.path})
  28.  
    print(self.config_map)
  29.  
     
  30.  
    # xml内容事件处理
  31.  
    def characters(self, content):
  32.  
    pass
  33.  
     
  34.  
    # 结束解析xml
  35.  
    def endElement(self, name):
  36.  
    pass
  37.  
    # xml结束标签调用
  38.  
    def endDocument(self):
  39.  
    print("******配置文件解析结束******")
  40.  
     
  41.  
     
  42.  
    if __name__ == "__main__":
  43.  
    # 创建一个 XMLReader
  44.  
    parser = xml.sax.make_parser()
  45.  
    # turn off namepsaces
  46.  
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
  47.  
    # 重写 ContextHandler
  48.  
    Handler = ConfigHandler()
  49.  
    parser.setContentHandler(Handler)
  50.  
    # 解析 xml 这里可以写xml 的具体路径,为了简单放在了同一个文件夹里面了
  51.  
    parser.parse("config.xml")

打印结果

demo2 读取同标签不同内容的xml

xml内容如下

  1.  
    <?xml version="1.0" encoding="UTF-8"?>
  2.  
    <config_content>
  3.  
    <type class="3年级">
  4.  
    <lib name="体育">优秀</lib>
  5.  
    <lib name="语文">一般</lib>
  6.  
    <lib name="数学">优秀</lib>
  7.  
    </type>
  8.  
    <type class="5年级">
  9.  
    <lib name="体育">一般</lib>
  10.  
    <lib name="语文">优秀</lib>
  11.  
    <lib name="数学">良好</lib>
  12.  
    </type>
  13.  
    </config_content>

python 代码如下

  1.  
    import xml.sax
  2.  
     
  3.  
     
  4.  
    class ConfigHandler(xml.sax.ContentHandler):
  5.  
     
  6.  
    def __init__(self):
  7.  
    self.tag = ""
  8.  
    self.name = ""
  9.  
    self.label = ""
  10.  
    self.content = ""
  11.  
     
  12.  
    # 启动文档
  13.  
    def startDocument(self):
  14.  
    print("******解析配置文件开始******")
  15.  
     
  16.  
    # 开始解析xml
  17.  
    def startElement(self, name, attributes):
  18.  
    self.tag = name
  19.  
    if name == "type":
  20.  
    self.name = attributes["class"]
  21.  
    print(self.name)
  22.  
    if name == "lib":
  23.  
    self.label = attributes["name"]
  24.  
    print(self.label)
  25.  
     
  26.  
    # xml内容事件处理
  27.  
    def characters(self, content):
  28.  
    self.content = content
  29.  
     
  30.  
    # 结束解析xml
  31.  
    def endElement(self, name):
  32.  
    if name == "lib":
  33.  
    print(self.content)
  34.  
     
  35.  
    # xml结束标签调用
  36.  
    def endDocument(self):
  37.  
    print("******配置文件解析结束******")
  38.  
     
  39.  
     
  40.  
    if __name__ == "__main__":
  41.  
    # 创建一个 XMLReader
  42.  
    parser = xml.sax.make_parser()
  43.  
    # turn off namepsaces
  44.  
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
  45.  
    # 重写 ContextHandler
  46.  
    Handler = ConfigHandler()
  47.  
    parser.setContentHandler(Handler)
  48.  
    # 解析 xml 这里可以写xml 的具体路径,为了简单放在了同一个文件夹里面了
  49.  
    parser.parse("config.xml")

打印结果如下


demo3 读取相同标签多个标题的xml

xml 内容如下

  1.  
    <?xml version="1.0" encoding="UTF-8"?>
  2.  
    <config_content>
  3.  
    <school name="第六中学">
  4.  
    <type class="2年级">
  5.  
    <Language>优秀</Language>
  6.  
    <Math>一般</Math>
  7.  
    <English>优秀</English>
  8.  
    </type>
  9.  
    <type class="5年级">
  10.  
    <Language>优秀</Language>
  11.  
    <Math>一般</Math>
  12.  
    <English>优秀</English>
  13.  
    </type>
  14.  
    </school>
  15.  
    <school name="第九中学">
  16.  
    <type class="1年级">
  17.  
    <Language>优秀</Language>
  18.  
    <Math>一般</Math>
  19.  
    <English>优秀</English>
  20.  
    </type>
  21.  
    <type class="3年级">
  22.  
    <Language>优秀</Language>
  23.  
    <Math>一般</Math>
  24.  
    <English>优秀</English>
  25.  
    </type>
  26.  
    </school>
  27.  
    </config_content>

python 代码如下

  1.  
    import xml.sax
  2.  
     
  3.  
     
  4.  
    class ConfigHandler(xml.sax.ContentHandler):
  5.  
     
  6.  
    def __init__(self):
  7.  
    self.tag = ""
  8.  
    self.name = ""
  9.  
    self.label = ""
  10.  
    self.content = ""
  11.  
     
  12.  
    # 启动文档
  13.  
    def startDocument(self):
  14.  
    print("******解析配置文件开始******")
  15.  
     
  16.  
    # 开始解析xml
  17.  
    def startElement(self, name, attributes):
  18.  
    self.tag = name
  19.  
    if name == "school":
  20.  
    self.name = attributes["name"]
  21.  
    print(self.name)
  22.  
    if name == "type":
  23.  
    self.label = attributes["class"]
  24.  
    print(self.label)
  25.  
     
  26.  
    # xml内容事件处理
  27.  
    def characters(self, content):
  28.  
    self.content = content
  29.  
     
  30.  
    # 结束解析xml
  31.  
    def endElement(self, name):
  32.  
    if name == "Language":
  33.  
    print(self.content)
  34.  
    elif name == "Math":
  35.  
    print(self.content)
  36.  
    elif name == "English":
  37.  
    print(self.content)
  38.  
     
  39.  
    # xml结束标签调用
  40.  
    def endDocument(self):
  41.  
    print("******配置文件解析结束******")
  42.  
     
  43.  
     
  44.  
    if __name__ == "__main__":
  45.  
    # 创建一个 XMLReader
  46.  
    parser = xml.sax.make_parser()
  47.  
    # turn off namepsaces
  48.  
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
  49.  
    # 重写 ContextHandler
  50.  
    Handler = ConfigHandler()
  51.  
    parser.setContentHandler(Handler)
  52.  
    # 解析 xml 这里可以写xml 的具体路径,为了简单放在了同一个文件夹里面了
  53.  
    parser.parse("config.xml")

打印结果如下:

******解析配置文件开始******
第六中学
2年级
优秀
一般
优秀
5年级
优秀
一般
优秀
第九中学
1年级
优秀
一般
优秀
3年级
优秀
一般
优秀
******配置文件解析结束******

最后总结,python 使用sax 读取xml 不难,可能存在组合数据的时候出现数据重现的问题,这个可以在拼接完数据之后,清空一下数据源,试试看,由于需求不一样,这里就不在写各种需求的组合数据了,大家注意一下数据重复问题即可。

posted @ 2021-11-02 14:40  clutch-man  阅读(964)  评论(0)    收藏  举报