xml_hivenet模块说明¶
xml_hivenet模块主要实现了xml文件的简单处理处理,模块使用lxml.etree进行底层处理。
支持的主要功能:
1、支持xml文件解析处理,以及与字典对象的相互转换;
2、支持html文件解析(基于xpath);
3、扩展支持xpath2.0语法。
SimpleXml的基本使用参考¶
基本使用说明¶
1、构造函数
示例:xmldoc = SimpleXml('test.xml', obj_type=EnumXmlObjType.File)
主要参数如下:
@param {object} xml_obj - 要装载的报文载体(与obj_type结合来判断是什么对象),例如(仅供参考):
obj_type = EnumXmlObjType.File 时,obj为文件路径
obj_type = EnumXmlObjType.FileHandle 时,obj为文件句柄
obj_type = EnumXmlObjType.String 时,obj为报文文本
@param {EnumXmlObjType} obj_type=EnumXmlObjType.File - xml对象类型
@param {string} encoding=encoding - 装载字符编码,如果传None代表自动判断
@param {bool} use_chardet=True - 当自动判断的时候,是否使用chardet库
@param {str} parser='xml' - 解析器类型,默认为xml
xml - 标准xml解析器
html - html解析器,兼容html一些不规范的地方
@param {dict} register_namespace=None - 注册命名空间别名,格式为:
{prefix: uri, prefix: uri, ... } 其中prefix和uri都为字符串
注册命名空间后,后续的节点就可以通过tag='{uri}tagname'的方式添加带命名空间的节点
@param {bool} use_xpath2=False - 使用xpath2.0,默认只支持xpath1.0
@param {**kwargs} kwargs - 扩展的装载参数,包括XMLParser的参数
attribute_defaults - inject default attributes from DTD or XMLSchema
dtd_validation - validate against a DTD referenced by the document
load_dtd - use DTD for parsing
no_network - prevent network access for related files (default: True)
ns_clean - clean up redundant namespace declarations
recover - try hard to parse through broken XML
remove_blank_text - discard blank text nodes that appear ignorable
装载时是否将空白文本去掉,只有含这个参数,打印时pretty_print才生效
remove_comments - discard comments
remove_pis - discard processing instructions
strip_cdata - replace CDATA sections by normal text content (default: True)
compact - save memory for short text content (default: True)
collect_ids - use a hash table of XML IDs for fast access (default: True, always True with DTD validation)
resolve_entities - replace entities by their text value (default: True)
huge_tree - disable security restrictions and support very deep trees
target - a parser target object that will receive the parse events
schema - an XMLSchema to validate against
2、提供各类函数获取及修改节点值和属性,主要的检索使用XPath语法;
3、支持另存为文件
示例:xmldoc.save('test1.xml', encoding='utf-8', xml_declaration=True)
@param {string|object} file=None - 要保存的文件的完整路径,如果不传代表修改原文件
注:也可以传入打开的文件句柄
@param {string} encoding=None - 文件编码,如果为None代表使用创建时的编码
@param {**kwargs} kwargs - 扩展的装载参数,包括ElementTree.write的参数
xml_declaration=None - 控制是否在文件中添加xml的声明,True - 一直添加, False - 不添加
如果传None,代表只有encoding不是US-ASCII or UTF-8 or Unicode的时候才添加声明
存在命名空间的情况¶
对于存在命名空间的情况,SimpleXml并不支持“{namespace}tag”这种类型的xPath语法处理,标准的使用方法如下:
# 指定命名空间字典,key值为命名空间的别名,可自定义
_ns = {
'people': 'http://people.example.com',
'role': 'http://characters.example.com'
}
# 获取节点值,需注意xPath中命名空间下的每个节点都需要指定别名
_text = _pfile.get_value('people:actor[1]/people:name', default='None', namespaces=_ns)
_text = _pfile.get_value(
'/people:actors/people:actor[1]/role:character[1]', default='None', namespaces=_ns)
# 创建带命名空间的节点,节点tag需要带命名空间的指定标识"{namespace}"
_tag = '{%s}%s' % (_ns['role'], 'tagname')
_node = ET.Element(_tag, nsmap=_ns)
_pfile.append_node('/people:actors', _node, namespaces=_ns)
将指定节点生成字典对象¶
to_dict函数可以将指定的节点生成字典对象(需注意不支持节点属性的情况),规则如下:
1、访问字典从节点的标签(tag)作为key,例如根节点的tag为data,则可通过_dict[’data’]进行对应的节点信息访问;
例如:
<data>
<a>val1</a>
<b>val2</b>
</data>
转换为字典:{'data': {'a': 'val1', 'b': 'val2'} }
2、xml中可通过type属性指定节点的类型,支持 dict, list, tuple, bool, int, float, string 这7种类型:其中dict 类型是默认类型,在字典中对应的value是一个字典,key为子节点的tag; bool, int, float, string 类型在字典中对应的value是节点的text转换过来的值;list、tuple是列表类型,在字典中对应得value是列表;
例如:
<data type='dict'>
<a>val1</a>
<b type='int'>3</b>
<c type='list'>
<c1>v1</c1>
<c2>v2</c2>
<c3><d>d1</d></c3>
</c>
</data>
转换为字典:
{
'data': {
'a': 'val1',
'b': 3,
'c': ['v1', 'v2', {'d': 'd1'}]
}
}
3、如果节点没有指定type属性,将自动根据子节点判断当前节点的类型,如果当前节点没有子节点,按string类型转换;如果当前节点有子节点,且子节点的tag没有重复情况,则按dict类型转换;如果子节点的tag有重复,则按list类型转换;
4、可以通过item_dict_xpaths参数指定某个list节点的列表项,不是直接取节点值,而是生成key值为tag的列表项:
例如:
<data>
<a type='list'>
<a1>x1</a1>
<a2>x2</a2>
</a>
<c type='list'>
<c1>v1</c1>
<c2>v2</c2>
<c3><d>d1</d></c3>
</c>
<data>
指定item_dict_xpaths={'/data/c': None}
转换为字典:
{
'data': {
'a': ['x1', 'x2'],
'c': [{'c1': 'v1'}, {'c2': 'v2'}, {'c3': {'d': 'd1'}}, ]
}
}
将字典对象添加到xml中¶
可以通过 set_value_by_dict 函数将字典对象添加到xml文档的指定节点中,程序会自动判断类型并进行相应转换,示例如下:
# 创建SimpleXml对象
_doc = SimpleXml('<root><a type="list"><item>test1</item></a><b></b></root>',
obj_type=EnumXmlObjType.String)
# 要添加到b节点下的字典对象
_dict = {
'b': True, 'c': 10, 'd': 3.4, 'e': 'teste', 'f': [
False, 11, 4.5, 'haha', {'g': 'gteset', 'h': False}
],
'i': {'a': 'tet', 'b': 'ddd'}
}
# 执行添加动作,通过with_type指定自动识别对象类型
_doc.set_value_by_dict('/root/b', _dict, with_type=True, debug=True)
print(_doc.to_string())
执行结果显示如下:
<root>
<a type="list">
<item>test1</item>
</a>
<b>
<b type="bool">true</b>
<c type="int">10</c>
<d type="float">3.4</d>
<e>teste</e>
<f type="list">
<item type="bool">false</item>
<item type="int">11</item>
<item type="float">4.5</item>
<item>haha</item>
<item>
<g>gteset</g>
<h type="bool">false</h>
</item>
</f>
<i>
<a>tet</a>
<b>ddd</b>
</i>
</b>
</root>
lxml.etree的基本使用参考¶
官方参考文档见:https://lxml.de/api/lxml-module.html
主要方法列表¶
访问元素属性 Element.tag(): 字符串类型,标识标识次元素类型 Element.text(): 元素内容 Element.attrib(): 属性字典 Element.clear(): 清楚所有子元素 Element.get(key, default=None): 获取key的元素属性,返回属性值,默认None Element.items(): 将元素属性以元组形式返回 Element.keys(): 列表形式返回属性名称 Element.set(key, value): 将元素上的属性设置为value
元素子元素操作 append(subelement): 添加子元素 extend(subelements):零个或多个元素序列追加子元素 find(match, namespaces=None):查找匹配第一个子元素,返回一个元素示例或None,match为标签名或xpath路径 findall(match, namespaces=None): 按照标签名称寻找子元素,match为标签名或者xpath路径 findtext(match, default=None, namespaces=None):返回匹配到的第一个子元素的文本,match可以是标签名或xpath路径,如果一个元素都匹配不到,返回default的值 insert(index, element):在元素指定位置插入子元素 iter(tag=None): 使用当前元素作为跟创建树迭代器 iterfind(match, namespaces=None): 按照标签名和xpath查找所有匹配的子元素,返回迭代 itertext():创建文本迭代器,迭代器按照文本顺序遍历元素和子元素,返回全部文本 remove(subelement): 从元素中删除子元素
遍历XML节点¶
1、遍历指定节点的子节点
import xml.etree as ET
tree = ET.parse('demo.xml')
root = tree.getroot() # 获得根节点
# 遍历子节点,可以通过该方法遍历递归遍历所有节点
for child in root:
print('%s %s' % (child.tag, child.attrib))
2、遍历所有节点重可符合匹配条件的节点
for n in root.iter(tag='neighbor'):
# 遍历所有节点中tag为'neighbor'的节点
print(n.attrib)
查找节点¶
1、通过XPath查找对象
for n in root.findall(".//year/..[@name='Singapore']")
print(n.attrib)
2、带命名空间的情况
xml示例文件:
<?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>
方法1:
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(' |-->%s' % char.text)
方法2(推荐):
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(' |-->%s' % char.text)
添加节点¶
1、先创建要添加的节点元素
# 生成新节点:ET.Element(tag, attrib={}, **extra)
# <a attr1='value1' attr2='value2' />
a = ET.Element('a', attrib={'attr1': 'value1', 'attr2': 'value2'})
# <b>b text</b>
b = ET.Element('b', text='b text')
# <c>c text</c>c-tail
c = ET.Element('c', text='c text', tail='c-tail')
# 组合节点:ET.SubElement(parent, tag, attrib={}, **extra)
# <a attr1='value1' attr2='value2'><d /></a>
d = ET.SubElement(a, 'd')
2、添加节点到根节点
# <a attr1='value1' attr2='value2'><d /><b>b text</b><c>c text</c>c-tail</a>
n = a.append(
b.append(c)
)
# 添加到根节点
root.append(n)
XPath参考¶
具体参考学习网站:https://www.w3school.com.cn/xpath/index.asp
XML 实例文档¶
我们将在下面的例子中使用这个 XML 文档。
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
选取节点¶
XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。
下面列出了最有用的路径表达式:
| 表达式 | 描述 |
|---|---|
| nodename | 选取此节点的所有子节点。 |
| / | 从根节点选取。 |
| // | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
| . | 选取当前节点。 |
| .. | 选取当前节点的父节点。 |
| @ | 选取属性。 |
实例
在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| bookstore | 选取 bookstore 元素的所有子节点。 |
| /bookstore | 选取根元素 bookstore。 注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
| bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
| //book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
| bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
| //@lang | 选取名为 lang 的所有属性。 |
谓语(Predicates)¶
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
实例
在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| /bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
| /bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
| /bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
| /bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
| //title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
| //title[@lang='eng'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
| /bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
| /bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
选取未知节点¶
XPath 通配符可用来选取未知的 XML 元素。
| 通配符 | 描述 |
|---|---|
| * | 匹配任何元素节点。 |
| @* | 匹配任何属性节点。 |
| node() | 匹配任何类型的节点。 |
实例
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| /bookstore/* | 选取 bookstore 元素的所有子元素。 |
| //* | 选取文档中的所有元素。 |
| //title[@*] | 选取所有带有属性的 title 元素。 |
选取若干路径¶
通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
实例
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| //book/title | //book/price | 选取 book 元素的所有 title 和 price 元素。 |
| //title | //price | 选取文档中的所有 title 和 price 元素。 |
| /bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |