python 处理xml中的注释_python 处理xml 笔记

文档模型:用以描述词汇和文档结构,定义文档中将要出现的数据元素,元素之间的关系,以及元素的数量等

实现文档模型的方法:模式 和 DTD (document type definition 文档类型定义)

1 文档模型的用途

文档模型用于在处理文档之前,验证它的内容是否符合标准。

DTD是文档类型定义,表示文档模型的最原始的方法

在文件顶部声明后插入一行: library.dtd是系统上的DTD路径

DTD中元素频率和元素分组操作符

?指定0个或者1个前面出现的元素。

+ 指定一个或者多个前面出现的元素

,指定一列元素必须 以此特定的顺序出现 (title,author+)意味着书必须有一个标题,随后是一个或者多个作者,必须以该顺序出现

(list) 将元素组织在一起。应用于圆括号后的运算符适用于组中的所有元素。(author,editor)+的含义是一篇文档可能有多个作者与多个编辑。

!或 运算符。该运算符允许在多个选项之间选择 (author|editor)允许一本书有一个作者或者一个编辑,但是不能同时具有两者

* 指定前面的元素或组出现0 次或多次。(book,CD)*允许图书馆中有任意数目的书或者CD 或者什么都没有,是空的。

3 XPath 是在xml文档中描述位置和节点集合的语言。xpath表达式包含对某个节点必须匹配的模式的描述。模式要么相对于一个上下文节点,要么由文档的根节点绝对定义。绝对路径以斜杠开始。路径的每一步之间由斜杠分隔开。

路径中的每一步包含3个部分:描述移动方向的轴,沿着该轴选择节点的测试,还有可选的谓词,它是节点必须满足的boolean 型测试。

如:ancestor-or-self::book[1]其中ancestor-or-self是轴,book是节点测试,[1]是谓词,指定选择满足所有其他条件的第一个节点。

节点测试既可以是一个函数,也可以是一个节点名称 book/node()将返回选择的书节点下的所有子节点,不管它们是文本还是元素。

@ 指定属性轴,这是attribute::的缩写

* 指定当前节点的所有子节点

//指定当前节点的所有后代节点 :descendant-or-self::*//的缩写。如果在xpath开头使用,它将匹配文档中任意地方的元素。

4 html是xml 的子集

为了解析一个html文档,必须创建一个从HTMLParser继承而来的类,并实现必要的方法

使用feed方法向解析器提供数据。可以每次提供一行数据,或者一次提供所有数据。

from html.parser import HTMLParser

class HeadingParser(HTMLParser):

inHeading=False

def handle_starttag(self,tag,attrs):#开始标签

if tag=="h1":

self.inHeading=True

print("found a heading 1")

def handle_data(self,data):#处理标签内容

if self.inHeading:

print(data)

def handle_endtag(self,tag): #结束标签

if tag=="h1":

self.inHeading=False

hParser=HeadingParser()

file=open("headings.html","r")

html=file.read()

file.close()

hParser.feed(html)

5 在解析xml时,可以 选择两种不同类型的解析器:SAX和DOM

SAX代表XML的简单API它是基于流的事件驱动的解析器。这些事件称作 文档事件,在元素开始之处、元素结尾处、遇到文本节点或者遇到一个注释时都有可能发生。

当用SAX解析文档时,文档以期出现的顺序被读入和解析。解析器以数据流的方式打开该文件或者其他数据源如url,之后无论何时遇到任何元素都将引发事件。操作文档不够高效。对于文档转换,应该选择SAX,因为事件驱动的模型速度很快。

DOM的核心在于文档对象,它是XML文档基于树的表示形式。树中的元素称作节点对象,节点拥有属性、子节点、文本 等,它们以对象的形式存储在树中。能在内存中存储整个文档,并且以树的形式操作和搜索其中的元素。文档大时预先处理时间长,处理后快。

python中解析器:xml.sax 和xml.dom.minidom

xml.dom.minidom 中parse方法解析文档树 返回一个Document对象。文本存储于节点的data属性

parse()函数可以引用一个文件名称或一个打开的文件对象

from xml.dom.minidom import parse, parseString

dom1 = parse('c:\\temp\\mydata.xml') # parse an XML file by name

datasource = open('c:\\temp\\mydata.xml')

dom2 = parse(datasource) # parse an open file

dom3 = parseString('Some data some more data')

appendChild方法可以创建节点的结构

节点的方法 insertBefor(newChild,refChild)可以在节点的子节点列表中的任意位置插入新的子节点

方法replaceChild(newChild,oldChild)可以将一个子节点替换为别一个子节点

删除节点 首先需要得到要删除的节点的引用,随后再调用 removeChild(childNode)方法。删除后,调用unlink()方法强制对被删除的节点及它可能连接的子节点进行垃圾回收,xml.dom中不可用。

xml.dom.minidom方法:toprettyxml,它接收两个可选参数:一个是缩进字符串,一个是换行符。如果没有指定参数值,这两个参数分别默认为tabulator 和\n。该方法将DOM 打印为包含良好缩进的XML

xmlns:lib="http://server.domain.tld/NameSpaces/Library">

Sandman volumn

Neil Gaiman

Good omens

Neil Gamain

Terry Pratchett

"Repent,harlequin!" said the man

Harlan Ellison

以上的xml 保存在文件里去掉命名空间可以使用以下代码操作

import os

from xml.dom.minidom import parse

import xml.dom.minidom

def printLibrary(library):

books=myLibrary.getElementsByTagName("book")

for book in books:

print("*******book******")

print("Title:%s"%book.getElementsByTagName("title")[0].childNodes[0].data)

for author in book.getElementsByTagName("author"):

print("author:%s"%author.childNodes[0].data)

# open an xml file and parse it into a dom

myDoc=parse(r'E:\pythonscript\ch15\library.xml')

myLibrary=myDoc.getElementsByTagName("library")[0]

#get all the book elements in the library

books=myLibrary.getElementsByTagName("book")

#Insert a new book in the library

newBook=myDoc.createElement("book")

newBookTitle=myDoc.createElement("title")

titleText=myDoc.createTextNode("Beginning Python")

newBookTitle.appendChild(titleText)

newBook.appendChild(newBookTitle)

newBookAuthor=myDoc.createElement("author")

authorName=myDoc.createTextNode("Peter Norton,et al")

newBookAuthor.appendChild(authorName)

newBook.appendChild(newBookAuthor)

myLibrary.appendChild(newBook)

print("--------added a new book!")

#printLibrary(myLibrary)

#remove a book from the library

#find ellison book

for book in myLibrary.getElementsByTagName("book"):

for author in book.getElementsByTagName("author"):

if author.childNodes[0].data.find("Ellison")>=0:

print(author.childNodes[0].data)

removedBook=myLibrary.removeChild(book)

removedBook.unlink()

print("------------removed a book.")

#printLibrary(myLibrary)

print(myDoc.toprettyxml())

#write back to the library file

lib=open(r"E:\pythonscript\ch15\library.xml","w")

lib.write(myDoc.toprettyxml(" "))

lib.close()# 这里是个方法,如果没有 这个方法 则不能写入数据,文件一直被占用

使用sax 解析:

#!/usr/bin/python

from xml.sax import make_parser

from xml.sax.handler import ContentHandler

#begin bookHandler

class bookHandler(ContentHandler):

inAuthor=False

inTitle=False

def startElement(self,name,attributes):

if name=="book":

print("********book*********")

if name=="title":

self.inTitle=True

print("Title:",)

if name=="author":

self.inAuthor=True

print("Author:",)

def endElement(self,name):

if name=="title":

self.inTitle=False

if name=="author":

self.inAuthor=False

def characters(self,content):

if self.inTitle or self.inAuthor:

print(content)

#end bookHandler

parser=make_parser()

parser.setContentHandler(bookHandler())

parser.parse("library.xml")

解析器xml.sax使用Handler对象解析文档过程中发生的事件。Handler可能是ContentHandler/DTDHandler /EntityResolver/ErrorHandler一个sax应用程序必须实现符合这些接口的处理程序类,并为解析器设置处理程序

接口ContentHandler包含了被文件事件触发的方法,例如元素和字符数据的开始和结束等。在解析字符数据时,解析器可以选择将结果作为一整块数据返回,或者作为若干小的以空白分隔的数据块返回,所以在处理一块文本的过程中需要反复调用characters方法。

make_parser方法创建一个新的解析器对象并将它返回。

6 lxml 使用cmd.exe pip install lxml 安装lxml

lxml是python利用libxml2 和libxslt库的快速、丰富特性的唯一绑定,并且它通过一个简单的api允许处理HTML /xml

包lxml使用了略作修改的ElementTreeAPI

导入lxml:import lxml

from lxml import etree

元素类:元素是ElementTreeAPI的主要容器对象,提供了xml树功能的核心,它们拥有属性并且包含文本.

元素类遵守标准的xml树层次,因此既能支持父元素也能支持子元素。

>>> import lxml

>>> from lxml import etree

>>> author=etree.Element("Horror") #创建新的元素类author,并赋予一个标签名称:Horror

>>> print(author.tag)

Horror

>>> writer1=etree.SubElement(author,"NeilGaiman")# 一个元素的子元素 创建一个新的子元素 ,它的标签是NeilGaiman,父元素是author

>>> writer2=etree.SubElement(author,"StephenKing")

>>> writer3=etree.SubElement(author,"CliveBarker")

>>> print(etree.tostring(author))

b''

>>> writer=author[0] #元素类也是列表,可以使用列表函数

>>> print(writer.tag)

NeilGaiman

>>> for writer in author:

print(writer.tag)

NeilGaiman

StephenKing

CliveBarker

元素可以包含属性,描述元素。

>>> author=etree.Element("author",audience="Adult")

>>> print(author.get("audience"))

Adult

get()方法可以从元素中提取数据,set()方法设置属性或都添加属性

>>> author.set("testpro","protect")

>>> etree.tostring(author)

b''

还可以向元素中添加文本

>>> html=etree.Element("html")

>>> body=etree.SubElement(html,"body")

>>> h1=etree.SubElement(body,"h1")

>>> h1.text="Introduction"

>>> paragraph=etree.SubElement(body,"p")

>>> paragraph.text="here is some text representing our paragraph"

>>> etree.tostring(html)

b'

Introduction

here is some text representing our paragraph

'

打印元素的文本:

>>> etree.tostring(paragraph,method="text")

b'here is some text representing our paragraph'

lxml解析函数:

fromstring()

>>> sentence="here is a sentence"

>>> info=etree.fromstring(sentence)

>>> print(info.tag)

info

>>> print(info.text)

here is a sentence

XML()

>>> info=etree.XML("here is a sentence")

>>> print(info.tag)

info

>>> print(info.text)

here is a sentence

>>> etree.tostring(info)

b'here is a sentence'

>>> import io

>>> newsentence=io.StringIO("This is another sentence")

>>> somesentence=etree.parse(newsentence)

>>> etree.tostring(somesentence)

b'This is another sentence'

>>> printit=somesentence.getroot()

>>> print(printit.tag)

info

>>> print(printit.text)

This is another sentence

dom解析xml

import xml.dom.minidom

from xml.dom.minidom import parse

dom1=parse(r'E:\pythonscript\ch15\config.xml')

myconfig=dom1.getElementsByTagName("config")[0]

dire=myconfig.getElementsByTagName("utilitydirectory")[0]

print(dire.childNodes[0].data)

uti=myconfig.getElementsByTagName("utility")[0]

print(uti.childNodes[0].data)

mode1=myconfig.getElementsByTagName("mode")[0]

print(mode1.childNodes[0].data)

#!/usr/bin/python

from xml.sax import make_parser

from xml.sax.handler import ContentHandler

class configHandler(ContentHandler):

isUtilDir=False

isUtil=False

isMode=False

def startElement(self,name,attributes):

if name=="utilitydirectory":

self.isUtilDir=True

print("------------utility directory-----",)

if name=="utility":

self.isUtil=True

print("--------------utility----------",)

if name=="mode":

self.isMode=True

print("---------------mode--------------",)

def endElement(self,name):

if name=="utilitydirectory":

isUtilDir=False

if name=="utility":

isUtil=False

if name=="mode":

isMode=False

def characters(self,content):

if self.isUtilDir or self.isUtil or self.isMode:

print(content)

parser=make_parser()

parser.setContentHandler(configHandler())

parser.parse(r"E:\pythonscript\ch15\config.xml")

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值