Python 如何使用本地DTD文件使用lxml解析XML文件?

Python 如何使用本地DTD文件使用lxml解析XML文件?,python,xml,lxml,dtd,Python,Xml,Lxml,Dtd,我试图在python中使用lxml解析DBLP数据集。但是,它给出了以下错误: lxml.etree.XMLSyntaxError:未定义实体“uuml”,第54行第43列 DBLP确实提供了用于定义实体的DTD文件。如何使用该文件解析DBLP XML文档 这是我目前的代码: filename = sys.argv[1] dtd_name = sys.argv[2] db_name = sys.argv[3] conn = sqlite3.connect(db_name) dblp_reco

我试图在python中使用lxml解析DBLP数据集。但是,它给出了以下错误:

lxml.etree.XMLSyntaxError:未定义实体“uuml”,第54行第43列

DBLP确实提供了用于定义实体的
DTD
文件。如何使用该文件解析DBLP XML文档

这是我目前的代码:

filename = sys.argv[1]
dtd_name = sys.argv[2]
db_name = sys.argv[3]

conn = sqlite3.connect(db_name)

dblp_record_types_for_publications = ('article', 'inproceedings', 'proceedings', 'book', 'incollection',
    'phdthesis', 'masterthesis', 'www')

# read dtd
dtd = ET.DTD(dtd_name) #pylint: disable=E1101

# get an iterable
context = ET.iterparse(filename, events=('start', 'end'), load_dtd=True, #pylint: disable=E1101
    resolve_entities=True) 

# turn it into an iterator
context = iter(context)

# get the root element
event, root = next(context)

n_records_parsed = 0
for event, elem in context:
    if event == 'end' and elem.tag in dblp_record_types_for_publications:
        pub_year = None
        for year in elem.findall('year'):
            pub_year = year.text
        if pub_year is None:
            continue

        pub_title = None
        for title in elem.findall('title'):
            pub_title = title.text
        if pub_title is None:
            continue

        pub_authors = []
        for author in elem.findall('author'):
            if author.text is not None:
                pub_authors.append(author.text)

        # print(pub_year)
        # print(pub_title)
        # print(pub_authors)
        # insert the publication, authors in sql tables
        pub_title_sql_str = pub_title.replace("'", "''")
        pub_author_sql_strs = []
        for author in pub_authors:
            pub_author_sql_strs.append(author.replace("'", "''"))

        conn.execute("INSERT OR IGNORE INTO publications VALUES ('{title}','{year}')".format(
            title=pub_title_sql_str,
            year=pub_year))
        for author in pub_author_sql_strs:
            conn.execute("INSERT OR IGNORE INTO authors VALUES ('{name}')".format(name=author))
            conn.execute("INSERT INTO authored VALUES ('{author}','{publication}')".format(author=author,
                publication=pub_title_sql_str))

        elem.clear()
        root.clear()

        n_records_parsed += 1
        print("No. of records parsed: {}".format(n_records_parsed))

conn.commit()
conn.close()

按照mzjn在注释中的建议,将DTD文件保存在与XML文件相同的目录中,并确保XML文档的doctype声明(
)中的DTD文件名与DTD文件名匹配后,将不再出现语法错误。

您可以添加自定义URI解析器:


如果XML文档具有doctype声明(
),并且dblp.dtd与XML文件位于同一目录中,并且使用了
load\u dtd=True
,那么我不会得到任何语法错误。我认为在这种情况下使用
dtd=ET.dtd(dtd\u name)
没有任何效果。
class DTDResolver(etree.Resolver):
    def resolve(self, system_url, public_id, context):
        return self.resolve_filename(os.path.join("/path/to/dtd/file", system_url), context)

context.resolvers.add(DTDResolver())