SAX 混淆 XML 中具有相同名称的两个节点

HelpASisterOut

我有一个 XML,我需要使用 SAX 在 python 中解析它。

这是我的 XML 的一小部分:

<MovieRating>
  <Movie Id="1">
    <Title>Father Figures</Title>
    <Duration>01:53:00</Duration>
    <Description>Upon learning that their mother has been lying to them for years about their allegedly deceased father, two fraternal twin brothers hit the road in order to find him.</Description>
    <Release_Date>2017-12-22</Release_Date>
    <Image_URL>https://image.com/1.jpg</Image_URL>
    <Country>USA</Country>
    <Genres>
      <Genre Id="5">
        <Title>Comedy</Title>
        <Description>None</Description>
      </Genre>
    </Genres>
    </Movies>
</MovieRating>

我正在尝试解析它并将其保存到数据库中,如下所示:

import sqlite3
import xml.sax 

class MoviesHandler(xml.sax.ContentHandler):
    def __init__(self):
        self.sql_attr_name = None
        self.sql_attrs = dict()
        self.conn = None

    def startDocument(self):
        self.conn = sqlite3.connect('moviez_sax.db')
        c = self.conn.cursor()
        c.execute('DROP TABLE IF EXISTS MOVIE')
        c.execute('''
                    CREATE TABLE IF NOT EXISTS Movie (
                Id           INTEGER        NOT NULL,
                Title        VARCHAR (1000) NOT NULL,
                Duration     TIME           NOT NULL,
                Description  VARCHAR (5000),
                Release_Date DATE           NOT NULL,
                Image_URL    VARCHAR (1000),
                Country      VARCHAR (150), 
                PRIMARY KEY (Id)
            );''');

    def endDocument(self):
        self.conn.commit()
        self.conn.close()


    def startElement(self, xml_name, xml_attrs):
        #print("start element", xml_name)
        if xml_name.lower() == 'movierating':
            pass
        if xml_name.lower() == 'movie':
            self.sql_attr_name = None
            self.sql_attrs = {
                'Id' : '',
                'Title' : '',
                'Duration' : '',
                'Description' : '',
                'Release_Date' : '',
                'Image_URL' : '',
                'Country':''
            }
            self.sql_attrs['Id'] += xml_attrs['Id']
        elif xml_name.lower() in ['id', 'title', 'duration', 'description' , 'release_date', 'image_url','country']:
            self.sql_attr_name = xml_name
        else:
            pass

    def characters(self, text):
        if self.sql_attr_name is not None:
            self.sql_attrs[self.sql_attr_name] += text

    def endElement(self, xml_name):
        if xml_name.lower() == 'movie':
            c = self.conn.cursor()
            c.execute('INSERT INTO MOVIE(Id,Title,Duration,\
                       Description,Release_Date,Image_URL, Country) VALUES \
                       (?,?,?,?,?,?,?)',
                      (self.sql_attrs['Id'].strip(),
                       self.sql_attrs['Title'].strip(),
                       self.sql_attrs['Duration'].strip(),
                       self.sql_attrs['Description'].strip(),
                       self.sql_attrs['Release_Date'].strip(),
                       self.sql_attrs['Image_URL'].strip(),
                       self.sql_attrs['Country'].strip())) 

if __name__ == '__main__':
    parser = xml.sax.make_parser()
    parser.setContentHandler(MovieRatingHandler())
    parser.parse(open('movies.xml','r'))

我的问题是,每当我阅读时self.sql_attrs['Title'].strip(),它都会从两个节点读取 TITLE 节点:电影和流派

并且它保存了两个连接的值。就像在那个例子中一样,我得到的标题值是:

Father Figures \n Comedy

有没有办法向 SAX 指定要读取的节点标题以及要读取的节点路径?因为我有许多具有相同名称的节点,但我想单独阅读“电影”和“流派”并将它们保存在两个不同的表中。

谢谢你。

塔伦·拉瓦尼

你需要在这两种情况下,记录事件genremovie然后,您将使用堆栈/列表推送当前节点。

在这种情况下,您也应该维护一个基于节点的字典。下面只是对您的代码的更新,不是最有效的更新,但展示了如何扩展您的示例

import sqlite3
import xml.sax

class MoviesHandler(xml.sax.ContentHandler):
    def __init__(self):
        self.sql_attr_name = None
        self.nodes = []
        self.sql_attrs = dict()
        self.conn = None

    def startDocument(self):
        self.conn = sqlite3.connect('moviez_sax.db')
        c = self.conn.cursor()
        c.execute('DROP TABLE IF EXISTS MOVIE')
        c.execute('''
                    CREATE TABLE IF NOT EXISTS Movie (
                Id           INTEGER        NOT NULL,
                Title        VARCHAR (1000) NOT NULL,
                Duration     TIME           NOT NULL,
                Description  VARCHAR (5000),
                Release_Date DATE           NOT NULL,
                Image_URL    VARCHAR (1000),
                Country      VARCHAR (150), 
                PRIMARY KEY (Id)
            );''');

    def endDocument(self):
        self.conn.commit()
        self.conn.close()


    def startElement(self, xml_name, xml_attrs):
        #print("start element", xml_name)
        if xml_name.lower() == 'movierating':
            pass
        if xml_name.lower() == 'genre':
            self.nodes.append(xml_name)
            self.sql_attrs[xml_name] = {
                'Title': '',
                'Description': '',
            }
        if xml_name.lower() == 'movie':
            self.nodes.append(xml_name)
            self.sql_attr_name = None
            self.sql_attrs[xml_name] = {
                'Id' : '',
                'Title' : '',
                'Duration' : '',
                'Description' : '',
                'Release_Date' : '',
                'Image_URL' : '',
                'Country':''
            }
            self.sql_attrs[xml_name]['Id'] += xml_attrs['Id']
        elif xml_name.lower() in ['id', 'title', 'duration', 'description' , 'release_date', 'image_url','country']:
            self.sql_attr_name = xml_name
        else:
            self.sql_attr_name = None
            pass

    def characters(self, text):
        if self.sql_attr_name is None or len(self.nodes) == 0:
            return

        if self.sql_attrs[self.nodes[-1]] is not None:
            self.sql_attrs[self.nodes[-1]][self.sql_attr_name] += text

    def endElement(self, xml_name):
        if xml_name.lower() in ['movie', 'genre']:
            self.nodes.pop()

        if xml_name.lower() == 'movie':
            c = self.conn.cursor()
            c.execute('INSERT INTO MOVIE(Id,Title,Duration,\
                       Description,Release_Date,Image_URL, Country) VALUES \
                       (?,?,?,?,?,?,?)',
                      (self.sql_attrs[xml_name]['Id'].strip(),
                       self.sql_attrs[xml_name]['Title'].strip(),
                       self.sql_attrs[xml_name]['Duration'].strip(),
                       self.sql_attrs[xml_name]['Description'].strip(),
                       self.sql_attrs[xml_name]['Release_Date'].strip(),
                       self.sql_attrs[xml_name]['Image_URL'].strip(),
                       self.sql_attrs[xml_name]['Country'].strip()))


if __name__ == '__main__':
    parser = xml.sax.make_parser()
    parser.setContentHandler(MoviesHandler())
    parser.parse(open('movies.xml','r'))

正如您所看到的调试会话,标题是正确的

在职的

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Android中的SAX XML

使用SAX解析器,如何解析具有相同名称标签但元素不同的xml文件?

Android:SAX解析具有相同标签的XML

在Sax中结束XML的早期解析

在xml解析中面临org.xml.sax.SAXParseException异常

在另一个节点中具有相同名称的XML节点

XML具有xsi:type属性时,Sax解析异常

当多个节点具有相同名称时,如何在XML中编辑特定节点的值?

解析具有相同名称的子节点的XML文件

读取具有相同名称的不同xml节点

使用Python xml.sax打开名称空间模式

使用R为xml文件中的所有节点提取具有相同名称的属性

XML Pull Parser和SAX Parser有什么区别

如何在SQL中拆分具有相同子代名称的两个xml标记

在Sax XML解析器中获取父子层次结构

parseString 在 xml.sax (Python) 中对我不起作用

返回xml2中具有相同名称的节点

从两个具有相同标签结构的xml文件的差异中创建一个节点

使用SAX Parser的Android XML

R XML-将父节点和子节点(具有相同名称)组合到数据框中

在PowerShell中添加具有相同名称的XML元素

jQuery XML解析,两个不同的节点,相同的名称

在两个名称空间中解组具有相同属性名称的XML属性

具有节点具有相同名称的xml的XSLT转换

如何搜索具有相同名称和相同级别的 XML 节点值?

使用带有sax的Python解析具有多个元素的XML

在 PostgreSQL 中混淆具有相同长度的名称

SAX与XmlTextReader-C#中的SAX

SQL:如何将多个具有相同名称的xml节点选择到以逗号分隔的列表中