网页分析和xml.etree库

        源代码: Lib/xml/etree/ElementTree.py


        该xml.etree.ElementTree模块实现了一个简单高效的 API,用于解析和创建 XML 数据。

一、说明

        这是一个简短的使用教程xml.etree.ElementTree(ET简而言之)。目标是演示该模块的一些构建块和基本概念。xml.etree是Python标准库中的一个子模块,用于处理XML(Extensible Markup Language)文档的解析和操作。它提供了一组简单的API,可以用于创建、处理、解析和生成XML文档。其中,ElementTree模块是最常用的模块,它提供了一种简单的方式来处理XML文档,包括读取、修改、创建和保存XML文档。由于XML在数据交换和数据存储方面的广泛应用,xml.etree在Python中具有重要的作用。

二、etree的基本概念

2.1 XML 树和元素

        XML 本质上是一种分层数据格式,最自然的表示方式是使用树。 ET有两个类用于此目的 - ElementTree将整个 XML 文档表示为一棵树,并 Element表示该树中的单个节点。与整个文档的交互(从文件读取和写入)通常在级别上完成ElementTree。与单个 XML 元素及其子元素的交互是在该Element级别上完成的。

2.2 解析 XML 

        我们将使用以下 XML 文档作为本节的示例数据:

<?xml version="1.0"?>
<data><country name="Liechtenstein"><rank>1</rank><year>2008</year><gdppc>141100</gdppc><neighbor name="Austria" direction="E"/><neighbor name="Switzerland" direction="W"/></country><country name="Singapore"><rank>4</rank><year>2011</year><gdppc>59900</gdppc><neighbor name="Malaysia" direction="N"/></country><country name="Panama"><rank>68</rank><year>2011</year><gdppc>13600</gdppc><neighbor name="Costa Rica" direction="W"/><neighbor name="Colombia" direction="E"/></country>
</data>

        我们可以通过读取文件来导入这些数据:

import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()

        或者直接从字符串:

root = ET.fromstring(country_data_as_string)

        fromstring()将 XML 从字符串直接解析为Element,它是解析树的根元素。其他解析函数可能会创建一个ElementTree. 检查文档以确定。

        作为Element,root具有标签和属性字典:

>>>
>>> root.tag
'data'
>>> root.attrib
{}

        它还具有我们可以迭代的子节点:

>>>
>>> for child in root:
...     print(child.tag, child.attrib)
...
country {'name': 'Liechtenstein'}
country {'name': 'Singapore'}
country {'name': 'Panama'}

        子节点是嵌套的,我们可以通过索引访问特定的子节点:

>>>
>>> root[0][1].text
'2008'

笔记

 

并非 XML 输入的所有元素最终都会成为解析树的元素。目前,该模块会跳过输入中的任何 XML 注释、处理指令和文档类型声明。尽管如此,使用该模块的 API 而不是从 XML 文本解析构建的树可以在其中包含注释和处理指令;生成 XML 输出时将包含它们。TreeBuilder可以通过将自定义实例传递给构造函数来访问文档类型声明XMLParser 。

2.2.1 Pull API 用于非阻塞解析

该模块提供的大多数解析功能都要求在返回任何结果之前立即读取整个文档。可以使用 an XMLParser并将数据增量地输入其中,但它是一个推送 API,在回调目标上调用方法,这对于大多数需求来说太低级且不方便。有时,用户真正想要的是能够增量地解析 XML,而不阻塞操作,同时享受完全构造的Element对象的便利。

执行此操作的最强大工具是XMLPullParser. 它不需要阻塞读取来获取 XML 数据,而是通过XMLPullParser.feed()调用增量地提供数据。要获取已解析的 XML 元素,请调用XMLPullParser.read_events(). 这是一个例子:

>>>
>>> parser = ET.XMLPullParser(['start', 'end'])
>>> parser.feed('<mytag>sometext')
>>> list(parser.read_events())
[('start', <Element 'mytag' at 0x7fa66db2be58>)]
>>> parser.feed(' more text</mytag>')
>>> for event, elem in parser.read_events():
...     print(event)
...     print(elem.tag, 'text=', elem.text)
...
end
mytag text= sometext more text

明显的用例是以非阻塞方式运行的应用程序,其中 XML 数据从套接字接收或从某些存储设备增量读取。在这种情况下,阻塞读取是不可接受的。

因为它非常灵活,所以XMLPullParser对于更简单的用例来说可能不方便。如果您不介意应用程序阻塞读取 XML 数据,但仍希望具有增量解析功能,请查看iterparse(). 当您正在阅读大型 XML 文档并且不想将其完全保存在内存中时,它会很有用。

2.2.2 寻找有趣的元素

Element有一些有用的方法可以帮助递归地迭代它下面的所有子树(它的子树,它们的子树,等等)。例如 Element.iter():

>>>
>>> for neighbor in root.iter('neighbor'):
...     print(neighbor.attrib)
...
{'name': 'Austria', 'direction': 'E'}
{'name': 'Switzerland', 'direction': 'W'}
{'name': 'Malaysia', 'direction': 'N'}
{'name': 'Costa Rica', 'direction': 'W'}
{'name': 'Colombia', 'direction': 'E'}

Element.findall()只查找带有当前元素直接子元素的标签的元素。 Element.find()查找具有特定标记的第一Element.text个子元素,并访问该元素的文本内容。 Element.get()访问元素的属性:

>>>
>>> for country in root.findall('country'):
...     rank = country.find('rank').text
...     name = country.get('name')
...     print(name, rank)
...
Liechtenstein 1
Singapore 4
Panama 68

通过使用XPath可以更复杂地指定要查找的元素。

2.2.3 修改 XML 文件

ElementTree提供了一种构建 XML 文档并将其写入文件的简单方法。该ElementTree.write()方法用于此目的。

创建后,Element可以通过直接更改其字段(例如Element.text)、添加和修改属性(Element.set()方法)以及添加新的子对象(例如使用Element.append())来操作对象。

假设我们要为每个国家/地区的排名添加 1,并向updated 排名元素添加一个属性:

>>>
>>> for rank in root.iter('rank'):
...     new_rank = int(rank.text) + 1
...     rank.text = str(new_rank)
...     rank.set('updated', 'yes')
...
>>> tree.write('output.xml')

我们的 XML 现在看起来像这样:

<?xml version="1.0"?>
<data><country name="Liechtenstein"><rank updated="yes">2</rank><year>2008</year><gdppc>141100</gdppc><neighbor name="Austria" direction="E"/><neighbor name="Switzerland" direction="W"/></country><country name="Singapore"><rank updated="yes">5</rank><year>2011</year><gdppc>59900</gdppc><neighbor name="Malaysia" direction="N"/></country><country name="Panama"><rank updated="yes">69</rank><year>2011</year><gdppc>13600</gdppc><neighbor name="Costa Rica" direction="W"/><neighbor name="Colombia" direction="E"/></country>
</data>

我们可以使用 删除元素Element.remove()。假设我们要删除排名高于 50 的所有国家/地区:

>>>
>>> for country in root.findall('country'):
...     # using root.findall() to avoid removal during traversal
...     rank = int(country.find('rank').text)
...     if rank > 50:
...         root.remove(country)
...
>>> tree.write('output.xml')

请注意,迭代时并发修改可能会导致问题,就像迭代和修改 Python 列表或字典时一样。因此,该示例首先收集所有与 , 匹配的元素 root.findall(),然后才迭代匹配列表。

我们的 XML 现在看起来像这样:

<?xml version="1.0"?>
<data><country name="Liechtenstein"><rank updated="yes">2</rank><year>2008</year><gdppc>141100</gdppc><neighbor name="Austria" direction="E"/><neighbor name="Switzerland" direction="W"/></country><country name="Singapore"><rank updated="yes">5</rank><year>2011</year><gdppc>59900</gdppc><neighbor name="Malaysia" direction="N"/></country>
</data>

2.2.5 构建 XML 文档

该SubElement()函数还提供了一种为给定元素创建新子元素的便捷方法:

>>>
>>> a = ET.Element('a')
>>> b = ET.SubElement(a, 'b')
>>> c = ET.SubElement(a, 'c')
>>> d = ET.SubElement(c, 'd')
>>> ET.dump(a)
<a><b /><c><d /></c></a>

2.2.6 使用命名空间解析 XML 

        如果 XML 输入具有名称空间,则表单中带有前缀的标签和属性prefix:sometag将扩展为 前缀被完整URI{uri}sometag替换的位置。另外,如果有默认名称空间,则完整的 URI 会添加到所有非前缀标签的前面。

        下面是一个包含两个命名空间的 XML 示例,一个带有前缀“fictional”,另一个用作默认命名空间:

<?xml version="1.0"?>
<actors xmlns:fictional="http://characters.example.com"xmlns="http://people.example.com"><actor><name>John Cleese</name><fictional:character>Lancelot</fictional:character><fictional:character>Archie Leach</fictional:character></actor><actor><name>Eric Idle</name><fictional:character>Sir Robin</fictional:character><fictional:character>Gunther</fictional:character><fictional:character>Commander Clement</fictional:character></actor>
</actors>

        find()搜索和浏览此 XML 示例的一种方法是手动将 URI 添加到 a或的 xpath 中的每个标记或属性 findall():

root = fromstring(xml_text)
for actor in root.findall('{http://people.example.com}actor'):name = actor.find('{http://people.example.com}name')print(name.text)for char in actor.findall('{http://characters.example.com}character'):print(' |-->', char.text)

        搜索命名空间 XML 示例的更好方法是使用您自己的前缀创建字典并在搜索函数中使用这些前缀:

ns = {'real_person': 'http://people.example.com','role': 'http://characters.example.com'}for actor in root.findall('real_person:actor', ns):name = actor.find('real_person:name', ns)print(name.text)for char in actor.findall('role:character', ns):print(' |-->', char.text)

        这两种方法都输出:

John Cleese|--> Lancelot|--> Archie Leach
Eric Idle|--> Sir Robin|--> Gunther|--> Commander Clement

三、XPath 支持

        该模块对 用于在树中定位元素的XPath 表达式提供有限的支持。目标是支持缩写语法的一小部分;完整的 XPath 引擎超出了该模块的范围。

3.1 示例

        下面的示例演示了该模块的一些 XPath 功能。我们将使用解析 XMLcountrydata部分中的 XML 文档 :

import xml.etree.ElementTree as ETroot = ET.fromstring(countrydata)# Top-level elements
root.findall(".")# All 'neighbor' grand-children of 'country' children of the top-level
# elements
root.findall("./country/neighbor")# Nodes with name='Singapore' that have a 'year' child
root.findall(".//year/..[@name='Singapore']")# 'year' nodes that are children of nodes with name='Singapore'
root.findall(".//*[@name='Singapore']/year")# All 'neighbor' nodes that are the second child of their parent
root.findall(".//neighbor[2]")

对于带有命名空间的 XML,请使用通常的限定{namespace}tag符号:

# All dublin-core "title" tags in the document
root.findall(".//{http://purl.org/dc/elements/1.1/}title")

3.2 支持的 XPath 语法

句法

意义

tag

选择具有给定标签的所有子元素。例如,spam选择名为 的所有子元素spam,并spam/egg选择所有egg名为 的子元素中 名为 的所有孙元素spam。 {namespace}*选择给定命名空间中的所有标签,{*}spam选择在任何(或没有)命名空间中命名的标签 spam,并且{}* 仅选择不在命名空间中的标签。

版本 3.8 中的更改:添加了对星号通配符的支持。

*

选择所有子元素,包括注释和处理指令。例如,*/egg 选择所有名为 的孙子egg

.

选择当前节点。这在路径的开头最有用,表明它是相对路径。

//

选择当前元素下所有级别上的所有子元素。例如,.//egg选择egg整个树中的所有元素。

..

选择父元素。None如果路径尝试到达起始元素(该元素find被调用)的祖先,则返回。

[@attrib]

选择具有给定属性的所有元素。

[@attrib='value']

选择给定属性具有给定值的所有元素。该值不能包含引号。

[@attrib!='value']

选择给定属性不具有给定值的所有元素。该值不能包含引号。

3.10 版本中的新功能。

[tag]

选择具有名为 的子元素的所有元素 tag。仅支持直系子女。

[.='text']

选择完整文本内容(包括后代)等于给定 的所有元素text

3.7 版本中的新功能。

[.!='text']

选择其完整文本内容(包括后代)不等于给定 的所有元素 text

3.10 版本中的新功能。

[tag='text']

选择具有名为 的子元素的所有元素 tag,其完整文本内容(包括后代)等于给定text

[tag!='text']

选择所有具有名为 的子元素, tag其完整文本内容(包括后代)不等于给定 的元素text

3.10 版本中的新功能。

[position]

选择位于给定位置的所有元素。位置可以是整数(1 是第一个位置)、表达式last() (最后一个位置)或相对于最后一个位置的位置(例如last()-1)。

        谓词(方括号内的表达式)前面必须有标记名称、星号或其他谓词。 position谓词前面必须有标记名称。

四、旧版参考资料

4.1 功能

1)规范化数据

        xml.etree.ElementTree.canonicalize(xml_data=None*out=Nonefrom_file=None**options)

转换功能。

        规范化是一种标准化 XML 输出的方法,允许逐字节比较和数字签名。它减少了 XML 序列化程序的自由度,而是生成更受约束的 XML 表示形式。主要限制涉及命名空间声明的放置、属性的顺序和可忽略的空格。

        此函数采用 XML 数据字符串 ( xml_data ) 或文件路径或类文件对象 ( from_file ) 作为输入,将其转换为规范形式,并使用 out file (-like) 对象(如果提供)将其写出,或者如果没有,则将其作为文本字符串返回。输出文件接收文本,而不是字节。因此,应该以带有编码的文本模式打开它utf-8 。

典型用途:

xml_data = "<root>...</root>"
print(canonicalize(xml_data))with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file:canonicalize(xml_data, out=out_file)with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file:canonicalize(from_file="inputfile.xml", out=out_file)

配置选项如下( options ):

  • with_comments:设置为 true 以包含注释(默认值: false)

  • strip_text:设置为 true 以去除文本内容前后的空格

    (默认值:假)

  • rewrite_prefixes:设置为 true 以用“n{number}”替换命名空间前缀

    (默认值:假)

  • qname_aware_tags:一组 qname 感知标签名称,其中前缀

    应在文本内容中替换(默认:空)

  • qname_aware_attrs:一组 qname 感知属性名称,其中前缀

    应在文本内容中替换(默认:空)

  • except_attrs:一组不应序列化的属性名称

  • except_tags:一组不应序列化的标签名称

在上面的选项列表中,“一组”指的是任何字符串的集合或可迭代,不需要排序。

3.8 版本中的新功能。

2)注释

xml.etree.ElementTree.Comment(text=None)

        注释元素工厂。此工厂函数创建一个特殊元素,该元素将由标准序列化程序序列化为 XML 注释。注释字符串可以是字节串或 Unicode 字符串。 text是包含注释字符串的字符串。返回表示评论的元素实例。

请注意,XMLParser会跳过输入中的注释,而不是为其创建注释对象。ElementTree仅当使用其中一种方法将注释节点插入到树中时,An才会包含注释节点Element。

3)转储

xml.etree.ElementTree.dump(elem)

将元素树或元素结构写入 sys.stdout。该函数只能用于调试。

确切的输出格式取决于实现。在此版本中,它被编写为普通的 XML 文件。

elem是元素树或单个元素。

版本 3.8 中的更改:该dump()函数现在保留用户指定的属性顺序。

4)从指定字符串解析文本

        xml.etree.ElementTree.fromstring(textparser=None)

        从字符串常量中解析 XML 部分。与 相同XML()。 text 是包含 XML 数据的字符串。 parser是一个可选的解析器实例。XMLParser如果未给出,则使用标准解析器。返回一个Element实例。

 5)从指定字符串list解析文本

        xml.etree.ElementTree.fromstringlist (textparser= None ) 

        从一系列字符串片段中解析 XML 文档。 序列是包含 XML 数据片段的列表或其他序列。 parser是一个可选的解析器实例。XMLParser 如果未给出,则使用标准解析器。返回一个Element实例。

4.2 版本3.2中的新功能。

        xml.etree.ElementTree.indent(treespace='  'level=0)

        将空格附加到子树以在视觉上缩进树。这可用于生成打印精美的 XML 输出。 可以是 Element 或 ElementTree。 space是将为每个缩进级别插入的空白字符串,默认情况下为两个空格字符。要在已缩进的树内缩进部分子树,请将初始缩进级别作为level传递。

4.3 新的3.9 版本中的新功能。

1)检查对象是否有效

        xml.etree.ElementTree.iselement(element)

        检查对象是否看起来是有效的元素对象。 element是一个元素实例。True如果这是一个元素对象,则返回。

2) 部分解析元素树

        xml.etree.ElementTree.iterparse(sourceevents=Noneparser=None)

        将 XML 部分逐步解析为元素树,并向用户报告发生的情况。 source是包含 XML 数据的文件名或文件对象 。 events是要报告的一系列事件。支持的事件是字符串"start""end""comment"、 "pi""start-ns""end-ns" “ns”事件用于获取详细的命名空间信息)。如果省略事件"end",则仅报告事件。 parser是一个可选的解析器实例。XMLParser如果未给出,则使用 标准 解析器。解析器必须是 的子类 XMLParser并且只能使用默认值TreeBuilder作为目标。返回一个提供对的迭代器;它有一个属性,一旦被完全读取,该属性就会引用生成的 XML 树的根元素。(event, elem)root

        请注意,在iterparse()增量构建树时,它会阻止对(或其命名的文件)的读取。因此,它不适合无法进行阻塞读取的应用程序。有关完全非阻塞解析,请参阅XMLPullParser。

注意:iterparse()仅保证在发出“start”事件时看到起始标记的“>”字符,因此属性已定义,但此时 text 和 tail 属性的内容未定义。这同样适用于元素子元素;他们可能在场,也可能不在场。

如果您需要完全填充的元素,请查找“结束”事件。

自 3.4 版起已弃用:解析器参数。

版本 3.8 中进行了更改:comment添加pi了 和 事件。

xml.etree.ElementTree.parse(sourceparser=None)

--解析元素

将 XML 部分解析为元素树。 source是包含 XML 数据的文件名或文件对象。 parser是一个可选的解析器实例。XMLParser如果未给出,则使用标准解析器。返回一个 ElementTree实例。

xml.etree.ElementTree.ProcessingInstruction(targettext=None

--处理指令 

        PI元件工厂。该工厂函数创建一个特殊元素,该元素将被序列化为 XML 处理指令。 target是包含 PI 目标的字符串。 text是包含 PI 内容(如果给定)的字符串。返回一个元素实例,表示一条处理指令。

        请注意,XMLParser跳过输入中的处理指令,而不是为其创建注释对象。ElementTree仅当使用其中一种方法将处理指令节点插入到树中时, An 才会包含处理指令节点Element。

xml.etree.ElementTree.register_namespace(prefixuri

 注册命名空间 

        注册命名空间前缀。注册表是全局的,给定前缀或命名空间 URI 的任何现有映射都将被删除。 prefix是命名空间前缀。 uri是命名空间 uri。如果可能的话,此命名空间中的标签和属性将使用给定的前缀进行序列化。

3.2 版本中的新功能。

xml.etree.ElementTree.SubElement(parenttagattrib={}**extra)

--子元素 

子元素工厂。此函数创建一个元素实例,并将其附加到现有元素。

元素名称、属性名称和属性值可以是字节串或 Unicode 字符串。 Parent是父元素。 tag是子元素名称。 attrib是一个可选字典,包含元素属性。 extra包含附加属性,以关键字参数形式给出。返回一个元素实例。

xml.etree.ElementTree.tostring(elementencoding='us-ascii'method='xml'*xml_declaration=Nonedefault_namespace=Noneshort_empty_elements=True)

        --生成 XML 元素(包括所有子元素)的字符串表示形式

         元素是一个Element实例。 编码 1是输出编码(默认为 US-ASCII)。用于encoding="unicode"生成 Unicode 字符串(否则,生成字节串)。 方法 是"xml","html""text"(默认为"xml")。 xml_declarationdefault_namespaceshort_empty_elements与 中的含义相同ElementTree.write()。返回包含 XML 数据的(可选)编码字符串。

3.4 版中的新功能:short_empty_elements参数。

3.8 版中的新增功能: xml_declaration和default_namespace参数。

版本 3.8 中的更改:该tostring()函数现在保留用户指定的属性顺序。

xml.etree.ElementTree.tostringlist(elementencoding='us-ascii'method='xml'*xml_declaration=Nonedefault_namespace=Noneshort_empty_elements=True

--生成 XML 元素(包括所有子元素)的字符串表示形式。

 元素是一个Element实例。 编码 1是输出编码(默认为 US-ASCII)。用于encoding="unicode"生成 Unicode 字符串(否则,生成字节串)。 方法 是"xml","html""text"(默认为"xml")。 xml_declarationdefault_namespaceshort_empty_elements与 中的含义相同ElementTree.write()。返回包含 XML 数据的(可选)编码字符串列表。它不保证任何特定的顺序,除了。b"".join(tostringlist(element)) == tostring(element)

3.2 版本中的新功能。

3.4 版中的新功能:short_empty_elements参数。

3.8 版中的新增功能: xml_declaration和default_namespace参数。

版本 3.8 中的更改:该tostringlist()函数现在保留用户指定的属性顺序。

xml.etree.ElementTree.XML(textparser=None)

--从字符串常量中解析 XML 部分

该函数可用于在 Python 代码中嵌入“XML 文字”。 text是包含 XML 数据的字符串。 parser是一个可选的解析器实例。XMLParser如果未给出,则使用标准 解析器。返回一个Element实例。

xml.etree.ElementTree.XMLID(textparser=None)

 -- 从字符串常量中解析 XML 部分,并返回一个从元素 id:s 映射到元素的字典

 text是包含 XML 数据的字符串。 parser是一个可选的解析器实例。XMLParser如果未给出,则使用标准 解析器。Element返回包含实例和字典的元组 。

4.3.1 X包括支持

        该模块通过帮助程序模块为XInclude 指令提供有限的支持 xml.etree.ElementInclude。该模块可用于根据树中的信息将子树和文本字符串插入元素树中。

        示例

        下面是一个演示 XInclude 模块的使用的示例。要在当前文档中包含 XML 文档,请使用{http://www.w3.org/2001/XInclude}include元素并将parse属性设置为"xml",并使用href属性指定要包含的文档。

<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="source.xml" parse="xml" />
</document>

        默认情况下,href属性被视为文件名。您可以使用自定义加载程序来覆盖此行为。另请注意,标准帮助程序不支持 XPointer 语法。

        要处理此文件,请照常加载它,并将根元素传递给模块xml.etree.ElementTree:

from xml.etree import ElementTree, ElementIncludetree = ElementTree.parse("document.xml")
root = tree.getroot()ElementInclude.include(root)

        ElementIninclude 模块将该元素替换为source.xml{http://www.w3.org/2001/XInclude}include文档中的根元素。结果可能看起来像这样:

<document xmlns:xi="http://www.w3.org/2001/XInclude"><para>This is a paragraph.</para>
</document>

        如果省略parse属性,则默认为“xml”。href 属性是必需的。

        要包含文本文档,请使用该{http://www.w3.org/2001/XInclude}include元素,并将parse属性设置为“text”:

<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">Copyright (c) <xi:include href="year.txt" parse="text" />.
</document>

结果可能类似于:

<document xmlns:xi="http://www.w3.org/2001/XInclude">Copyright (c) 2003.
</document>

五、最新版功能资料

5.1 功能

        xml.etree.ElementIninclude.default_loaderhref解析编码=无

        默认加载程序。此默认加载程序从磁盘读取包含的资源。 href是一个 URL。 parse用于解析模式“xml”或“text”。 编码 是可选的文本编码。如果未给出,则编码为utf-8. 返回扩展的资源。如果解析模式为"xml",则这是一个 ElementTree 实例。如果解析模式为“text”,则这是一个 Unicode 字符串。如果加载器失败,它可以返回 None 或引发异常。

        xml.etree.ElementIninclude。包括elem loader = None base_url = None max_depth = 6

此函数扩展了 XInclude 指令。 elem是根元素。 loader是一个可选的资源加载器。如果省略,则默认为default_loader(). 如果给定,它应该是一个可调用的,实现与 相同的接口 default_loader()。 base_url是原始文件的基本 URL,用于解析相对包含文件引用。 max_depth是递归包含的最大数量。限制降低恶意内容爆炸的风险。传递负值以禁用限制。

返回扩展的资源。如果解析模式为 "xml",则这是一个 ElementTree 实例。如果解析模式为“text”,则这是一个 Unicode 字符串。如果加载器失败,它可以返回 None 或引发异常。

3.9 版本中的新功能: base_url和max_depth参数。

4.4.2 元素对象

        xml.etree.ElementTree类 元素(标签, attrib = {} , **额外

元素类。此类定义了 Element 接口,并提供了该接口的参考实现。

元素名称、属性名称和属性值可以是字节串或 Unicode 字符串。 tag是元素名称。 attrib是一个可选字典,包含元素属性。 extra包含附加属性,以关键字参数形式给出。

标签

一个字符串,标识该元素代表什么类型的数据(换句话说,元素类型)。

文本

尾巴

这些属性可用于保存与元素关联的附加数据。它们的值通常是字符串,但也可以是任何特定于应用程序的对象。如果元素是从 XML 文件创建的,则text属性保存元素的开始标记与其第一个子标记或结束标记之间的文本,或者None,并且tail属性保存元素的结束标记与下一个标记之间的文本,或None。对于 XML 数据

<a><b>1<c>2<d/>3</c></b>4</a>

a元素具有Nonetext和tail属性,b元素具有texttail 属性c元素具有texttail 属性d元素具有texttail属性。 "1" "4" "2" None None "3"

要收集元素的内部文本,请参阅itertext()例如"".join(element.itertext())

应用程序可以在这些属性中存储任意对象。

属性

包含元素属性的字典。请注意,虽然 attrib值始终是真正的可变 Python 字典,但 ElementTree 实现可以选择使用其他内部表示形式,并且仅在有人要求时才创建字典。要利用此类实现,请尽可能使用下面的字典方法。

以下类似字典的方法适用于元素属性。

清除( ) 

重置一个元素。该函数删除所有子元素,清除所有属性,并将 text 和 tail 属性设置为None

获取默认=无

获取名为key的元素属性。

返回属性值,如果未找到属性,则返回默认值。

项目( ) 

以(名称,值)对序列的形式返回元素属性。属性以任意顺序返回。

( ) 

以列表形式返回元素属性名称。名称以任意顺序返回。

设置

将元素上的属性key设置为value

以下方法适用于元素的子元素(子元素)。

附加子元素

将元素子元素添加到该元素的内部子元素列表的末尾。TypeError如果子元素不是 则 引发Element。

扩展子元素

从具有零个或多个元素的序列对象追加子元素。TypeError如果子元素不是 则引发Element。

3.2 版本中的新功能。

查找匹配命名空间=无

查找第一个匹配match的子元素。 匹配可以是标签名称或路径。返回一个元素实例或None命名空间是从命名空间前缀到全名的可选映射。作为前缀传递'',将表达式中所有无前缀的标签名称移动到给定的命名空间中。

findall (匹配,命名空间= None ) 

按标签名称或 路径查找所有匹配的子元素。返回一个列表,其中包含按文档顺序排列的所有匹配元素。 命名空间是从命名空间前缀到全名的可选映射。作为前缀传递'',将表达式中所有无前缀的标签名称移动到给定的命名空间中。

findtext (匹配,默认= None ,命名空间= None ) 

查找第一个匹配match的子元素的文本。 匹配可以是标签名称或路径。返回第一个匹配元素的文本内容,如果未找到元素,则返回默认值。请注意,如果匹配元素没有文本内容,则返回空字符串。命名空间是从命名空间前缀到全名的可选映射。作为前缀传递'',将表达式中所有无前缀的标签名称移动到给定的命名空间中。

插入索引子元素

在此元素中的给定位置插入子元素。TypeError如果子元素不是 则引发 Element。

迭代器标签=无

创建一个以当前元素为根的树迭代器。迭代器按文档(深度优先)顺序迭代此元素及其下面的所有元素。如果tag不是None或,则迭代器仅返回tag'*'等于 tag 的元素。如果在迭代期间修改树结构,则结果是不确定的。

3.2 版本中的新功能。

iterfind (匹配,命名空间= None ) 

按标签名称或 路径查找所有匹配的子元素。返回一个可迭代对象,生成按文档顺序排列的所有匹配元素。命名空间是从命名空间前缀到全名的可选映射。

3.2 版本中的新功能。

迭代文本( ) 

创建一个文本迭代器。迭代器按文档顺序循环遍历该元素和所有子元素,并返回所有内部文本。

3.2 版本中的新功能。

makeelement (标签,属性

创建与此元素类型相同的新元素对象。不要调用此方法,SubElement()而是使用工厂函数。

删除子元素

从元素中删除子元素。与 find* 方法不同,此方法根据实例标识而不是标记值或内容来比较元素。

Element对象还支持以下用于处理子元素的序列类型方法:__delitem__(), __getitem__(), __setitem__(), __len__()。

注意:没有子元素的元素将测试为False。在 Python 3.14 中,测试元素的真值已被弃用,并且会引发异常。使用特定len(elem)或测试代替:elem is None

element = root.find('foo')if not element:  # careful!print("element not found, or element has no subelements")if element is None:print("element not found")

在 version 3.12 中更改:测试 Element 发出的真值DeprecationWarning。

在 Python 3.8 之前,元素的 XML 属性的序列化顺序是通过按属性名称排序来人为地预测的。基于现在保证的字典排序,这种任意重新排序在 Python 3.8 中被删除,以保留用户代码最初解析或创建属性的顺序。

一般来说,鉴于XML 信息集明确排除属性顺序来传递信息,用户代码应尽量不依赖于属性的特定顺序。代码应该准备好处理任何输入顺序。在需要确定性 XML 输出的情况下(例如,对于加密签名或测试数据集),该函数可以使用规范序列化canonicalize()。

在规范输出不适用但输出仍需要特定属性顺序的情况下,代码应旨在直接按所需顺序创建属性,以避免代码读者的感知不匹配。在难以实现的情况下,可以在序列化之前应用如下所示的配方,以独立于元素创建强制执行订单:

def reorder_attributes(root):for el in root.iter():attrib = el.attribif len(attrib) > 1:# adjust attribute order, e.g. by sortingattribs = sorted(attrib.items())attrib.clear()attrib.update(attribs)

4.4.3 元素树对象

xml.etree.ElementTree类 ElementTree元素=无文件=无

ElementTree 包装类。此类表示整个元素层次结构,并为与标准 XML 之间的序列化添加了一些额外的支持。

元素是根元素。该树使用 XML文件的内容(如果给定)进行初始化。

_setroot (元素

替换该树的根元素。这将丢弃树的当前内容,并将其替换为给定元素。小心使用。 element是一个元素实例。

查找匹配命名空间=无

与 相同Element.find(),从树的根部开始。

findall (匹配,命名空间= None ) 

与 相同Element.findall(),从树的根部开始。

findtext (匹配,默认= None ,命名空间= None ) 

与 相同Element.findtext(),从树的根部开始。

获取根目录( ) 

返回此树的根元素。

迭代器标签=无

创建并返回根元素的树迭代器。迭代器按节顺序循环遍历该树中的所有元素。 tag是要查找的标签(默认是返回所有元素)。

iterfind (匹配,命名空间= None ) 

与 相同Element.iterfind(),从树的根部开始。

3.2 版本中的新功能。

解析解析器=无

将外部 XML 部分加载到此元素树中。 source是文件名或文件对象。 parser是一个可选的解析器实例。XMLParser如果未给出,则使用标准解析器。返回节根元素。

文件编码= 'us-ascii' xml_declaration = None default_namespace = None方法= 'xml' * short_empty_elements = True

将元素树以 XML 形式写入文件。 file是文件名,或 打开用于写入的文件对象。 编码 1是输出编码(默认为 US-ASCII)。 xml_declaration控制是否应将 XML 声明添加到文件中。 如果不是 US-ASCII、UTF-8 或 Unicode(默认为),则使用False“从不”、“True始终”、“仅”。 default_namespace设置默认的 XML 命名空间(对于“xmlns”)。 方法是,或(默认为 )。仅关键字的short_empty_elements参数控制不包含内容的元素的格式设置。如果(默认),它们将作为单个自闭合标签发出,否则它们将作为一对开始/结束标签发出。NoneNone"xml""html""text""xml"True

输出是字符串 ( str) 或二进制 ( bytes)。这是由编码参数控制的。如果编码为 "unicode",则输出为字符串;否则,它是二进制的。请注意,如果它是一个打开的 文件对象,这可能会与文件类型冲突;确保您不要尝试将字符串写入二进制流,反之亦然。

3.4 版中的新功能:short_empty_elements参数。

在 version 3.8 中更改:该write()方法现在保留用户指定的属性顺序。

这是将要操作的 XML 文件:

<html><head><title>Example page</title></head><body><p>Moved to <a href="http://example.org/">example.org</a>or <a href="http://example.com/">example.com</a>.</p></body>
</html>

更改第一段中每个链接的属性“target”的示例:

>>>
>>> from xml.etree.ElementTree import ElementTree
>>> tree = ElementTree()
>>> tree.parse("index.xhtml")
<Element 'html' at 0xb77e6fac>
>>> p = tree.find("body/p")     # Finds first occurrence of tag p in body
>>> p
<Element 'p' at 0xb77ec26c>
>>> links = list(p.iter("a"))   # Returns list of all links
>>> links
[<Element 'a' at 0xb77ec2ac>, <Element 'a' at 0xb77ec1cc>]
>>> for i in links:             # Iterates through all found links
...     i.attrib["target"] = "blank"
...
>>> tree.write("output.xhtml")

4.4.4 QName 对象

xml.etree.ElementTree类 QName ( text_or_uri , tag = None ) 

QName 包装器。这可用于包装 QName 属性值,以便在输出上获得正确的命名空间处理。 text_or_uri是一个包含 QName 值的字符串,格式为 {uri}local,或者,如果给出了 tag 参数,则为 QName 的 URI 部分。如果给出 tag ,则第一个参数被解释为 URI,并且该参数被解释为本地名称。QName实例是不透明的。

4.4.5 树构建器对象

xml.etree.ElementTree类 TreeBuilder ( element_factory = None , * , comment_factory = None , pi_factory = None , insert_comments = False , insert_pis = False ) 

通用元素结构生成器。此构建器将一系列开始、数据、结束、注释和 pi 方法调用转换为格式良好的元素结构。您可以使用此类来使用自定义 XML 解析器或其他类似 XML 格式的解析器来构建元素结构。

element_factory当给定时,必须是一个可调用的,接受两个位置参数:一个标签和一个属性字典。预计会返回一个新的元素实例。

comment_factory和pi_factory函数在给出时,其行为应类似于和函数来创建注释和处理指令。如果没有给出,将使用默认工厂。当insert_comments和/或insert_pis为 true 时,如果注释/pi 出现在根元素内(但不在根元素之外),则它们将被插入到树中。Comment()ProcessingInstruction()

关闭( ) 

刷新构建器缓冲区,并返回顶级文档元素。返回一个Element实例。

数据数据

向当前元素添加文本。 数据是一个字符串。这应该是字节串或 Unicode 字符串。

结束标签

关闭当前元素。 tag是元素名称。返回闭合元素。

开始标签属性

打开一个新元素。 tag是元素名称。 attrs是包含元素属性的字典。返回打开的元素。

评论文字

使用给定的文本创建评论。如果insert_comments为真,这也会将其添加到树中。

3.8 版本中的新功能。

pi (目标,文本

使用给定的目标名称和文本创建注释。如果 insert_pis为真,这也会将其添加到树中。

3.8 版本中的新功能。

此外,自定义TreeBuilder对象还可以提供以下方法:

doctype (名称, pubid ,系统

处理文档类型声明。 name是文档类型名称。 pubid是公共标识符。 system是系统标识符。默认类中不存在此方法TreeBuilder。

3.2 版本中的新功能。

start_ns (前缀, uri ) 

每当解析器遇到新的命名空间声明时,在start()定义它的开始元素的回调之前调用。 前缀用于''默认命名空间,否则为声明的命名空间前缀名称。 uri是命名空间 URI。

3.8 版本中的新功能。

end_ns (前缀

end()在声明命名空间前缀映射的元素的回调之后调用,其中前缀的名称超出了范围。

3.8 版本中的新功能。

xml.etree.ElementTree类 C14NWriterTarget ( write , * , with_comments = False , strip_text = False , rewrite_prefixes = False , qname_aware_tags = None , qname_aware_attrs = None , except_attrs = None , except_tags = None ) 

C14N 2.0作家。参数与函数相同canonicalize()。该类不构建树,而是使用write函数将回调事件直接转换为序列化形式。

3.8 版本中的新功能。

4.4.6 XMLParser 对象

xml.etree.ElementTree类 XMLParser ( * ,目标= None ,编码= None ) 

此类是模块的低级构建块。它用于 xml.parsers.expat高效、基于事件的 XML 解析。它可以使用该方法增量地提供 XML 数据,并且通过调用目标feed()对象上的回调将解析事件转换为推送 API 。如果省略目标,则使用标准。如果给出编码1 ,则该值将覆盖 XML 文件中指定的编码。TreeBuilder 

版本 3.8 中已更改:参数现在仅包含关键字。不再支持html参数。

关闭( ) 

完成向解析器提供数据。返回调用构造时传递的目标close()方法的结果 ;默认情况下,这是顶级文档元素。

提要数据

将数据提供给解析器。 数据是编码数据。

XMLParser.feed()为每个开始标记调用target的方法,为每个结束标记调用 target 的方法,并通过 method 处理数据。有关更多支持的回调方法,请参阅该类。 调用 目标的方法。不仅可以用于构建树结构。这是计算 XML 文件最大深度的示例:start(tag, attrs_dict)end(tag)data(data)TreeBuilderXMLParser.close()close()XMLParser

>>>
>>> from xml.etree.ElementTree import XMLParser
>>> class MaxDepth:                     # The target object of the parser
...     maxDepth = 0
...     depth = 0
...     def start(self, tag, attrib):   # Called for each opening tag.
...         self.depth += 1
...         if self.depth > self.maxDepth:
...             self.maxDepth = self.depth
...     def end(self, tag):             # Called for each closing tag.
...         self.depth -= 1
...     def data(self, data):
...         pass            # We do not need to do anything with data.
...     def close(self):    # Called when all data has been parsed.
...         return self.maxDepth
...
>>> target = MaxDepth()
>>> parser = XMLParser(target=target)
>>> exampleXml = """
... <a>
...   <b>
...   </b>
...   <b>
...     <c>
...       <d>
...       </d>
...     </c>
...   </b>
... </a>"""
>>> parser.feed(exampleXml)
>>> parser.close()
4

4.4.7 XMLPullParser 对象

xml.etree.ElementTree类 XMLPullParser (事件=无

适合非阻塞应用程序的拉式解析器。它的输入端 API 与 的类似XMLParser,但不是将调用推送到回调目标,而是XMLPullParser收集解析事件的内部列表并让用户从中读取。events是要报告的一系列事件。支持的事件是字符串"start""end"、 "comment""pi""start-ns""end-ns"“ns”事件用于获取详细的命名空间信息)。如果省略事件"end",则仅报告事件。

提要数据

将给定的字节数据提供给解析器。

关闭( ) 

向解析器发出数据流已终止的信号。与此不同的是 XMLParser.close(),此方法总是返回None。解析器关闭时尚未检索到的任何事件仍可以使用 读取read_events()。

读取事件( ) 

返回在馈送到解析器的数据中遇到的事件的迭代器。迭代器产生对,其中event是表示事件类型的字符串(例如) , elem是遇到的对象或其他上下文值,如下所示。(event, elem)"end"Element

  • startend:当前元素。

  • commentpi: 当前注释/处理指令

  • start-ns:命名已声明的命名空间映射的元组。(prefix, uri)

  • end-ns:(None这可能会在未来版本中改变)

先前调用中提供的事件read_events()将不会再次产生。仅当从迭代器检索事件时,才会从内部队列消耗事件,因此多个读取器并行迭代从中获取的迭代器read_events()将产生不可预测的结果。

笔记

 

XMLPullParser仅保证在发出“start”事件时看到起始标记的“>”字符,因此属性已定义,但此时 text 和 tail 属性的内容未定义。这同样适用于元素子元素;他们可能在场,也可能不在场。

如果您需要完全填充的元素,请查找“结束”事件。

3.4 版本中的新功能。

版本 3.8 中进行了更改:comment添加pi了 和 事件。

4.4.8 例外情况

xml.etree.ElementTree类 解析错误

XML 解析错误,当解析失败时由该模块中的各种解析方法引发。此异常实例的字符串表示形式将包含用户友好的错误消息。此外,它将具有以下可用属性:

代码

来自 expat 解析器的数字错误代码。xml.parsers.expat有关错误代码及其含义的列表,请参阅 的文档 。

位置

行号列号的元组,指定错误发生的位置。

脚注

xml.etree.ElementTree — The ElementTree XML API — Python 3.12.0 documentation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/186658.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

送水服务预约小程序内容该如何做

无论小区还是办公楼等场景&#xff0c;送水服务往往有较高需求&#xff0c;同时该服务属于长期稳定性的&#xff0c;因此对品牌来说&#xff0c;如何打造品牌获取更多用户及转化非常重要&#xff0c;然而在实际订水过程中&#xff0c;又会面临着一些难题&#xff1a; 1、品牌传…

代码随想录算法训练营第四十六天|139. 单词拆分、多重背包问题、总结

第九章 动态规划part08 139. 单词拆分 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 注意&#xff1a;不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 关于字符串类型的题目还是…

ElementUI之el-progress动态修改进度条里面文本颜色与进度条色块统一

1.效果&#xff1a; 2.实现方式 通过行内style样式动态给整个progress赋颜色 再在样式里给进度条文字单独设置颜色为默认继承父级颜色就ok啦 <el-progress class"custom-progress" stroke-linecap"square" :style"{color:item.color}" :colo…

使用电阻检测仪是否能满足生产车间防静电要求

在现代工业生产中&#xff0c;静电对产品质量和人员安全造成的影响越来越受到重视。特别是在电子、半导体、化工等领域&#xff0c;静电问题可能导致产品损坏、人员触电等严重后果。因此&#xff0c;生产车间的防静电工作显得尤为重要。而电阻检测仪作为一种常用的防静电工具&a…

Java后端开发——JDBC入门实验

JDBC&#xff08;Java Database Connectivity&#xff09;是Java编程语言中用于与数据库建立连接并进行数据库操作的API&#xff08;应用程序编程接口&#xff09;。JDBC允许开发人员连接到数据库&#xff0c;执行各种操作&#xff08;如插入、更新、删除和查询数据&#xff09…

OpenAI开发者大会大模型圈开卷AI Agent? 实在智能布局前瞻已下“先手棋”

“平地起惊雷&#xff0c;至今有余音。” 去年的11月&#xff0c;OpenAI发布ChatGPT给科技圈劈下了一道惊雷&#xff0c;引爆了全世界的AI大模型热潮&#xff0c;全球科技巨头公司争先恐后地推出通用大模型&#xff0c;探索产业应用的可能。 短短一年后&#xff0c;北京时间1…

汇编-DUP操作符

DUP操作符使用整数表达式作为计数器&#xff0c; 为多个数据项分配存储空间。 在为字符串或数组分配存储空间时&#xff0c;这个操作符尤其有用&#xff0c;并且可以使用初始化或非初始化数据&#xff1a; .data BYTE 20 DUP(0) ;20个字节&#xff0c;都等于0 BYTE 20 …

电商项目之Java8函数式接口落地实践

文章目录 1 问题背景2 前言3 多处重复的重试机制代码4 优化后的代码5 进一步优化 1 问题背景 在电商场景中&#xff0c;会调用很多第三方的云服务&#xff0c;比如发送邮件、发起支付、发送验证码等等。由于网络存在抖动&#xff0c;有时候发起调用后会拿到500的状态码&#xf…

Linux学习第38天:Linux I2C 驱动实验(二):哥俩好

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 本节笔记主要学习I2C设备驱动编写及硬件原理图分析。 先把整个本节的思维导图贴出来&#xff1a; 二、I.MX6U的I2C适配器驱动分析 适配器驱动一般都是由SOC厂商提…

最新整理【剑侠情缘龙雀修复BGU版】linux服务端带授权后台+详细教程+包进游戏

搭建资源下载地址&#xff1a;最新整理【剑侠情缘龙雀修复BGU版】linux服务端带授权后台详细教程包进游戏 - 海盗空间

虚幻5 删除C盘缓存及修改缓存路径

一.修改C盘缓存 C盘缓存路径为&#xff1a; C:\Users\xx(这里是你的用户名)\AppData\Local\UnrealEngine\Common\DerivedDataCache 注意&#xff0c;如果没有AppData文件夹&#xff0c;请依次点击查看-勾选显示隐藏的项目&#xff0c;即可 可删除里面的所有文件即可 二.修改…

nanodet训练自己的数据集、NCNN部署到Android

nanodet训练自己的数据集、NCNN部署到Android 一、介绍二、训练自己的数据集1. 运行环境2. 数据集3. 配置文件4. 训练5. 训练可视化6. 测试 三、部署到android1. 使用官方权重文件部署1.1 下载权重文件1.2 使用Android Studio部署apk 2. 部署自己的模型【暂时存在问题】2.1 生成…

Win10 + VS017 编译SQLite3.12.2源码

参考&#xff1a; [1] WIN10 VS2019下编译GDAL3.0PROJ6SQLite_gdal 3 win10编译-CSDN博客 [2] 如何编译SQLite-How To Compile SQLite-CSDN博客 如何生成静态库&#xff1a; 参考&#xff1a; WIN10 VS2019下编译GDAL3.0PROJ6SQLite_gdal 3 win10编译-CSDN博客 如何生成exe:…

105.am40刷机(linux)折腾记1-前期的准备工作1

前段时间在某鱼上逛的时候&#xff0c;发现一款3399的盒子只要150大洋&#xff0c;内心就开始澎拜&#xff0c;一激动就下手了3台&#xff0c;花了450大洋&#xff08;现在想想&#xff0c;心都碎了一地&#xff09;。 然后自己又来来回回折腾了几天&#xff0c;目前能跑上fire…

viple入门(四)

&#xff08;1&#xff09;行打印 主要用于在运行窗口中显示数据&#xff0c;打印完成后&#xff0c;自动换行。 注意事项&#xff1a;不可同时打印两个数据&#xff0c;例如 解决方案1&#xff1a;使用或并&#xff0c;使得每次进入行打印的数据只有一个&#xff0c;缺点&am…

2020年五一杯数学建模B题基于系统性风险角度的基金资产配置策略分析解题全过程文档及程序

2020年五一杯数学建模 B题 基于系统性风险角度的基金资产配置策略分析 原题再现 近年来&#xff0c;随着改革开放程度的不断提高&#xff0c;我国经济运行中的各种风险逐渐暴露并集中传导和体现于金融领域。党的“十九大”报告提出“守住不发生系统性金融风险的底线”要求&am…

「Verilog学习笔记」4位数值比较器电路

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 这里要注意题目的“门级描述方式”&#xff0c;所以我们只能使用基本门电路&#xff1a;&,|,!,^,^~。 具体实现思路&#xff1a;通过真值表得出Y0 Y1 Y2的逻辑表达…

前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(三)

知者乐水&#xff0c;仁者乐山。 XMLHttpRequest AJAX原理 - XMLHttpRequest 前面与服务器交互使用的不是axios吗&#xff1f; ajax并不等于axios 我们使用的axios的内部&#xff0c;实际上对XHR对象/原理 的封装 为什么还要学习ajax&#xff1f; ①在一些静态网站项目中…

rabbitMq虚拟主机概念

虚拟主机是RabbitMQ中的一种逻辑隔离机制&#xff0c;用于将消息队列、交换机以及其他相关资源进行隔离。 在RabbitMQ中&#xff0c;交换机&#xff08;Exchange&#xff09;用于接收生产者发送的消息&#xff0c;并根据特定的路由规则将消息分发到相应的队列中。而虚拟主机则…

矩阵起源荣获第八届“创客中国”深圳市中小企业创新创业大赛三等奖

近日&#xff0c;2023年第八届“创客中国”深圳市中小企业创新创业大赛圆满落下帷幕&#xff0c;矩阵起源&#xff08;深圳&#xff09;信息科技有限公司凭借项目”MatrixOne 新一代超融合异构云原生数据库”荣获企业组三等奖。 本届大赛由深圳市工业和信息化局、深圳市中小企业…