python操作xml的学习记录

0. iterparse到终极理解,按文件流顺序解析,需要设置一些信号变量,用来只获取自己想要到数据,剔除不要的数据。
context=ET.iterparse(xm, events=(‘start’, ‘end’))
# context=iter(context)
# root=context.next()
for event, elem in context:
try:

            if event == 'start' and elem.tag == 'fileHeader':
                sqltimestamp=elem.get('startTime').replace('T','').replace('-','').replace(':','')
            elif event == 'end' and elem.tag == 'smr' :
                if 'MR.LteScPlr' in elem.text:
                    meas_sign=1
                else:
                    meas_sign=0
                elem.clear()
            elif event == 'start' and elem.tag == 'object':
                if meas_sign==1:
                    cellid=elem.get('id') 
            elif event == 'end' and elem.tag == 'v':
                if meas_sign==1:
                    text_plr = elem.text
                    if text_plr:
                        text_plr_list = text_plr.split(' ')
                        if len(text_plr_list)>10:
                            LteScPlrULQci1 = text_plr_list[0]
                            LteScPlrDLQci1 = text_plr_list[9]
                        if LteScPlrULQci1!='NIL':
                            tempindex=plr_interval(int(LteScPlrULQci1))
                            if cellid not in cell_dict.keys():
                                cell_dict[cellid]=mro_values[:]
                            cell_dict[cellid][tempindex]+=1                        
                        if LteScPlrDLQci1!='NIL':
                            tempindex=plr_interval(int(LteScPlrDLQci1))
                            if cellid not in cell_dict.keys():
                                cell_dict[cellid]=mro_values[:]
                            cell_dict[cellid][tempindex+28]+=1        
                elem.clear()                

            elif event == 'end' and elem.tag == 'object':
                elem.clear()
            elif event == 'end' and elem.tag == 'bulkPmMrDataFile':
                elem.clear()
            # else:
            #     elem.clear()

        except Exception as e:
            print(str(e),'mro elem do error'+gz)   
            elem.clear()

1、elementTree的iterparse()使用event、elem IN 遍历,当事件是start时,很多教材说此时解析到了elem的TAG而后面没有开始解析,这种说法容易迷惑人。此时开始了elem的start,想获得elem的text等内容都是可以的,因为已经定位了该elem,只要继续往下读就能获得其他内容,没有必要等到end才去获取TEXT、属性等内容,很多时候在start的时候就要获得属性内容(实时写入数据库),判断属性是否是所需elem,不需要的内容直接在start时就可以clear,不需要再解析缓存一遍,至少能快一些。
以上理解有误,实践起来结果并不准确,直到看到一篇文章,才明白原理:
http://effbot.org/zone/element-iterparse.htm
http://www.51testing.com/html/69/610069-3646742.html
events选项指定您要查看的事件(此版本中的可用事件是“start”,“end”,“start-ns”和“end-ns”,其中“ns”事件用于获取详细的命名空间 信息)。 如果省略该选项,则仅返回“end”事件。

注意:树构建器和事件生成器不一定是同步的; 后者通常落后一点。 这意味着当您获得元素的“开始”事件时,构建器可能已经使用内容填充了该元素。 但是,您不能依赖于此 - “开始”事件只能用于检查属性,而不是元素内容。 有关更多详细信息,请参阅此消息。https://mail.python.org/pipermail/xml-sig/2005-January/010838.html
“Jimmy Retzlaff写道:

我正在使用cElementTree.iterparse迭代XML文件。我认为
iterparse是一个很棒的主意 - 我发现它更方便
比SAX用于迭代处理。我遇到了一个问题
虽然…

对于我的大多数元素,start和end事件都包含
元素的文本(即element.text)。少数几个
元素,文本仅在结束事件中(即,element.text为None
在开始事件中但在结束事件中不是无)。文字是
在文件上使用cElementTree.parse时发现没有任何问题
相反。

我误解了什么,或者这可能是一个错误?

它需要更多文档;-)

以下是CHANGES文件中的评论:

elem对象是当前元素;对于“开始”事件,
元素本身已经创建(包括属性),但它
内容可能不完整;对于“结束”事件,所有子元素
已被处理。您可以使用“开始”标记进行计数
元素,检查属性,并检查是否存在某些标记
在树上。出于所有其他目的,请改用“end”处理程序。

在该文中,“可能不”实际上意味着“可能或不可能”。就是内容
可能是完整的,但这不是你可以或应该依赖的。

这样做的原因是事件不会与构建完美锁定
处理;在当前版本中,解析器可能会提前16k。
这意味着当你得到一个“开始”事件时,解析器经常被处理
事件内部的一切(特别是如果它足够小),但你不能
靠那个。

或者换句话说,对于开始事件,以下属性是有效的:

elem.tag
elem.attrib
父元素的标签和属性(如果你使用堆栈)
    需要跟踪他们)
(不是elem.text)
(不是elem.tail)
(不是elem [:])
您可以修改标记和属性
你可能会停止解析

对于最终活动,以下内容适用:

elem.tag
elem.attrib
elem.text
elem [:](即孩子们)
所有孩子的完整内容(包括尾巴)
(不是elem.tail)(但是所有的孩子尾巴)
您可以修改除elem.tail之外的所有属性
你可以重新排序/更新孩子
你可以删除孩子(例如,调用elem.clear()来标记它
    你完成了这个水平)
你可能会停止解析”

for event, elem in iterparse(source):
if elem.tag ==“record”:
… process record elements …
elem.clear(
上述模式有一个缺点; 它不会清除根元素,因此您最终会得到一个包含许多空子元素的元素。 如果您的文件很大,而不是很大,这可能是个问题。 要解决这个问题,您需要掌握根元素。 最简单的方法是启用启动事件,并保存对变量中第一个元素的引用
# get an iterable
context = iterparse(source, events=(“start”, “end”))
# turn it into an iterator
context = iter(context)
# get the root element
event, root = context.next()
for event, elem in context:
if event == “end” and elem.tag == “record”:
… process record elements …
root.clear()

2、elementTree在写XML时,属性是无序字典,一般按升序写入属性,重写序列化方法可以达到顺序写入目的,但比较麻烦。lxml可以解决属性顺序写入问题。只要将前者替换成from lxml import etree as ET 就行了。但后者缓存了父节点和框架,内存占用大些/解析慢些,但写入序列化速度很快,是优势。纯解析就用et,解析加写入就用lxml。

3、关于XML schema及命名空间
https://wenku.baidu.com/view/6733739d3086bceb19e8b8f67c1cfad6185fe913.html
https://www.cnblogs.com/ljzforever/archive/2009/05/20/1467792.html
XML schema是W3规范的内容,规范规定了schema内包含固定标签-element/attribute/text及内部数据类型,是个人和规范的接口。可以使用schema文件在其中自定义标签及自定义数据类型 simpletype/complextype.
使用targetnamespace属性,可以将自定义的标签、属性、数据类型等加载到自定义命名空间中,要使用该自定义命名空间,可以加载自定义命名空间所在xsd文件即可。

<?xml version="1.0" encoding="utf-8"?>

<xs:schema xmlns="" xmlns:xs=“http://www.w3.org/2001/XMLSchema” xmlns:msdata=“urn:schemas-microsoft-com:xml-msdata” id=“bulkPmMrDataFile”>
<xs:element name=“bulkPmMrDataFile” msdata:IsDataSet=“true” msdata:Locale=“en-US”>
xs:complexType
xs:sequence

<xs:element name=“fileHeader”>
xs:complexType
<xs:attribute name=“fileFormatVersion” type=“xs:string” use=“required”/>
<xs:attribute name=“reportTime” type=“xs:dateTime” use=“required”/>
<xs:attribute name=“startTime” type=“xs:dateTime” use=“required”/>
<xs:attribute name=“endTime” type=“xs:dateTime” use=“required”/>
<xs:attribute name=“period” type=“xs:int” use=“optional”/>
<xs:attribute name=“jobid” type=“xs:int” use=“optional”/>
</xs:complexType>
</xs:element>
(1)schema的作用就是定义xml的架构、元素定义。使用命名空间一般是xmlns:xs=“http://www.w3.org/2001/XMLSchema”,如果xmlns:xs 替换成xmlns,那该空间就是默认命名空间,元素不用带命名空间名称xs。schema规定使用"http://www.w3.org/2001/XMLSchema"命名空间,包含schema/element /attribite/text等基本标签。其它命名空间有自有的命名空间,可以自己定义自己的命名空间-xmlns:xx,凡事非默认命名空间的标签、属性等都要在标签名称前面加所属命名空间,如xx:tag。

(2)可以看到xmlns有的是网址,有的是其它URI,但是对于网址开头的命名空间有可能就有点疑惑了,它究竟代表的是什么?xaml文件被解析的时候会访问这个网址吗?如果这个网址那天不能get了,那我们的程序是不是就不能正常运行了。实际是所有URI只是命名空间的别名而已,它实际代表是命名空间集合:
以xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation这个为例,其实它就是System.Windows,System.Windows.Automation,System.Winjdows.Controls…等一系列命名空间的集合,是这个集合的【别名】,在浏览器输入这个网址有时候是不可访问的。如果自己定义类库的话,我把这个【别名】叫做张三也是可以的。微软建议,这个一般定义为公司网址,或者个人网址。
详见引用:https://blog.csdn.net/catshitone/article/details/71213371
(3)命名空间的作用是避免元素定义混淆、重复。也就是说xml中所有节点、属性名称在全网都是唯一的。
见:https://blog.csdn.net/yi412/article/details/70158876
(4)命名空间保存在xsd文件中,本身也是xml规范文件。自定义命名空间保存在本地,可供外使用,只要和需生成的xml文件在同一目录就行,需要在文件中加入文件名引用(Xxxx.xsd)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值