# 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']进行对应的节点信息访问;
```
例如:
val1
val2
转换为字典:{'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是列表;
```
例如:
val1
3
v1
v2
d1
转换为字典:
{
'data': {
'a': 'val1',
'b': 3,
'c': ['v1', 'v2', {'d': 'd1'}]
}
}
```
3、如果节点没有指定type属性,将自动根据子节点判断当前节点的类型,如果当前节点没有子节点,按string类型转换;如果当前节点有子节点,且子节点的tag没有重复情况,则按dict类型转换;如果子节点的tag有重复,则按list类型转换;
4、可以通过item_dict_xpaths参数指定某个list节点的列表项,不是直接取节点值,而是生成key值为tag的列表项:
```
例如:
x1
x2
v1
v2
d1
指定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('- test1
',
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())
执行结果显示如下:
- test1
true
10
3.4
teste
- false
- 11
- 4.5
- haha
-
gteset
false
tet
ddd
```
## 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示例文件:
```
John Cleese
Lancelot
Archie Leach
Eric Idle
Sir Robin
Gunther
Commander Clement
```
方法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 = ET.Element('a', attrib={'attr1': 'value1', 'attr2': 'value2'})
# b text
b = ET.Element('b', text='b text')
# c textc-tail
c = ET.Element('c', text='c text', tail='c-tail')
# 组合节点:ET.SubElement(parent, tag, attrib={}, **extra)
#
d = ET.SubElement(a, 'd')
```
2、添加节点到根节点
```
# b textc textc-tail
n = a.append(
b.append(c)
)
# 添加到根节点
root.append(n)
```
## XPath参考
具体参考学习网站:https://www.w3school.com.cn/xpath/index.asp
### XML 实例文档
我们将在下面的例子中使用这个 XML 文档。
```
Harry Potter
29.99
Learning XML
39.95
```
### 选取节点
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 元素。 |