2006年09月29日 星期五

Lost Season3 即将上演

首播时间:2006年10月04日
电视台: ABC
内容介绍:
  本剧集为美国ABC电视台自alias后播出的最具热门元素的最新剧集。ABC斥巨资于夏威夷拍摄,整个故事情节跌宕起伏,演员表演淋漓尽致,已成为黄金时段收视率最高的电视剧之一。
  故事从一位职业医生Jack的视角展开,主要讲述一架客机坠落在太平洋的孤岛上,共48名乘客侥幸生还。起初,人们庆幸生还,期盼救援部队的到来,他们慢慢发现这个小岛似乎曾经来过和他们一样的人们,他们的求救信号已经不停的播发了16年,但是,似乎没有人发现他们的存在……
  面对这种荒芜人烟的小岛,他们如何才能生存下去呢?没有好的医疗设备,Jack只能用最简陋的办法将奄奄一息的人们一个个救活。在为生存而抗争的过程中,Jack成了英雄……
  然而,即使英雄也会有不可告人的秘密...生还者形形色色,国籍、人种、文化背景、个性各异,14位主演中有兄妹,有父子,有朋友,有夫妻,也有敌人。他们既要克服恶劣的天气,在荒蛮的热带丛林中寻找食物、水源,还有一只在夜晚发出令所有人心惊胆战叫声的神秘生物;不断地有人神秘失踪和死亡...
losts.jpg

losts3.jpg

由 beat 发表于 下午01点06分 | 回复 (0)

2006年09月05日 星期二

豪斯医生-House 第三季

【频  道】:FOX
【剧  名】:House MD
【播出时间】:9月5日20点
【类  型】:剧情
【主  演】:
Hugh Laurie 饰 Dr. Gregory House
Lisa Edelstein 饰 Dr. Lisa Cuddy
Omar Epps 饰 Dr. Eric Foreman
Robert Sean Leonard 饰 Dr. James Wilson
Jennifer Morrison 饰 Dr. Allison Cameron
Jesse Spencer 饰 Dr. Robert Chase

【剧情简介】:
Gregory House是一位医生,不过他从来不和他的病人交流,能闪则闪,一根拐杖是他的标志,尖酸刻薄是他的风格,追求事实是他的行为准则,揭人伤疤是他的乐趣,他是恶医,却绝对不是庸医,相反作为一位内科医生,House的医术非常高明,他是一位诊断专家,医院甚至单独为他开设了一个诊断科,率领手下三位医生,或者说三只小鸭子,还有一位永远都会罩着他的魅力女上司和一位随时都会出手住他的好友兼同事,对抗一个一个查不出病因的疑难杂症。
由Paul Attanasio, Katie Jacobs, David Shore和Bryan Singer(非常嫌疑犯,X-men2和超人归来的导演)合力打造,本剧情节跌宕起伏,对白幽默诙谐且富含哲理,不容错过哦。携第二季FOX收视霸主之威,House第三季即将来到,House归来,将带给我们什么样的惊喜呢?又有什么新的疾病在等他?他的拐杖扔了吗?他的感情有进展吗?一切的一切,谨在06年秋天《豪斯医生》第三季,FR将倾情翻译制作,敬请期待。
【演员介绍】:
Hugh Laurie 饰 Dr. Gregory House
house.jpg
本名:James Hugh Calum Laurie
身高:189cm
简介:1959年6月11日生于英格兰牛津市,先后在伊顿公学和剑桥大学接受教育,大学时主修人类学和考古学。父亲是前奥运会双人皮划艇冠军,由于父亲的关系,Hugh Laurie年轻时立志做一个优秀的皮划艇运动员,他本人也曾代表英格兰国家队参加过世界青年皮划艇比赛,并获第四名,后来由于疾病的关系不得已放弃这一事业。1978年时,他在大学参加剧团的时候遇到了艾玛·汤普森,后者在演艺道路上给了他很大的帮助。Hugh Laurie还是一位畅销书作家,另外钢琴非常优秀,还曾一度进行过潜水训练。Hugh Laurie1989年和现任妻子乔.格林(Jo Green)结婚,并育有三个孩子。
Hugh Laurie从1982年起开始扮演各种电视角色,并制作、导演过很多节目,1995年参演李安导演的《理智与情感》,1999年参演《精灵鼠小弟》,2002年参演《精灵鼠小弟2》,2004年参演《凤凰劫》,同年并获得扮演《豪斯医生》男主角豪斯医生的机会,2006年获金球奖最佳男主角奖项。
爱好:摩托车,钢琴
偶像:克林特·伊斯特伍德(Clint Eastwood),史蒂夫·麦奎因(Steve Mcqueen),House片中他的老鼠名字就叫史蒂夫·麦奎因

Lisa Edelstein 饰 Dr. Lisa Cuddy
cuddy.jpg
本名:Lisa Edelstein
身高:168cm
简介:1967年生于美国马萨诸塞州波士顿,她在纽约大学学习戏剧时开始了职业演员生涯,毕业后一直在百老汇扮演各种角色,后进军电视业,扮演过一系列的配角,曾在《白宫风云》(West Wing)中扮演过一位应招女郎,2004年获得扮演《豪斯医生》女主角之一的Lisa Cuddy兼院长。
Lisa Edelstein是一位严格的素食主义者,并且是一位动物保护主义者。
爱好:写作,绘画,音乐制作

Omar Epps 饰 Dr. Eric Foreman
foreman.jpg
全名:Omar Hashim Epps
身高:179cm
简介:1973年7月23日生于美国纽约布鲁克林,10岁时开始写剧本,后进入纽约一家艺术高中读书,1992年起在电视上扮演各种角色,1996年参演电视剧《急诊室》(ER)扮演Dennis Gant医生,2004年和梅格•瑞恩合作参演《拳坛小妹》(Against the Ropes),2004年和Keisha Spivey结婚至今,并育有两个孩子,同年获得参演《豪斯医生》男主角之一的Foreman医生的机会。
言论:我会成为美国第一位黑人总统,既然里根能做到,我也可以---1999年

Robert Sean Leonard 饰 Dr. James Wilson
wilson.jpg
全名:Robert Lawrence Leonard
身高:183cm
简介:1969年2月28日生于美国新泽西州西木(Westwood)市,曾在哥伦比亚大学进修。曾经和格温妮斯·帕尔特洛有过一段感情。1986年开始出演电视角色,1989年参演《死亡诗社》,和一同参演的伊桑.霍克结识并成为好友至今。1993年曾参演马丁·西克塞斯导演的《纯真年代》。Robert Lawrence Leonard在纽约市有一家剧场公司。

Jennifer Morrison 饰 Dr. Allison Cameron
cameron.jpg
全名:Jennifer Morrison
身高:166cm
简介:1979年8月19日生于美国伊利诺伊州芝加哥市,父亲是该州一位著名的教师,高中时曾是学校的啦啦队长,毕业于芝加哥洛约拉大学,主修戏剧学。10岁左右时曾经和乔丹一起为体育杂志拍摄封面照片。Jennifer Morrison1994年起开始扮演角色, 2004年获得机会参演《豪斯医生》,2005年曾参演《史密斯夫妇》。

Jesse Spencer 饰 Dr. Robert Chase
chase.jpg
全名:Jesse Gordon Spencer
身高:179
简介:1979年2月12日生于澳大利亚墨尔本,父亲是一位医生,Jesse Spencer另有两个哥哥和一个妹妹,两个哥哥也都是医生。曾参加澳大利亚少年唱诗班,10岁起开始拉小提琴,同时钢琴也弹得很好,1994年开始出演电视节目,2004年获得参演《豪斯医生》男主角之一Robert Chase医生的机会
言论:我在墨尔本长大,墨尔本有300万人口,你在这里长大,会觉得这个城市好大哦,后来等我旅行归来,感觉墨尔本就是一个村子。我妈妈开车的时候,如果碰到15辆车堵了,就会对交通状况满腹抱怨,我说,这也叫堵车?


由 beat 发表于 下午10点48分 | 回复 (0)

2006年09月03日 星期日

PHP parse_url函数

parse_url
(PHP 3, PHP 4, PHP 5)

parse_url -- 解析 URL,返回其组成部分
描述
array parse_url ( string url )


此函数返回一个关联数组,包含现有 URL 的各种组成部分。如果缺少了其中的某一个,则不会为这个组成部分创建数组项。组成部分为:


scheme - 如 http

host

port

user

pass

path

query - 在问号 ? 之后

fragment - 在散列符号 # 之后


此函数并 不 意味着给定的 URL 是合法的,它只是将上方列表中的各部分分开。parse_url() 可接受不完整的 URL,并尽量将其解析正确。

注: 此函数对相对路径的 URL 不起作用。

例子 1. parse_url() 示例

$ php -r 'print_r(parse_url("http://username:password@hostname/path?arg=value#anchor"));'
Array
(
[scheme] => http
[host] => hostname
[user] => username
[pass] => password
[path] => /path
[query] => arg=value
[fragment] => anchor
)

$ php -r 'print_r(parse_url("http://invalid_host..name/"));'
Array
(
[scheme] => http
[host] => invalid_host..name
[path] => /
)

参见 pathinfo()、parse_str()、dirname() 与 basename()。

由 beat 发表于 上午01点01分 | 回复 (0)

2006年09月02日 星期六

彻底隐藏你HTML网页的源代码

<html>

<head><title>Test IFrame</title>
<script>
function clear() {
Source=document.body.firstChild.data;
document.open();
document.close();
document.body.innerHTML=Source;
}
</script>
</head>
<body onload=clear()>
<!--
<Iframe name=tag align=center width="100%" src="http://www.nkstars.org/beat/" scrolling="no" frameborder="0" onload="this.height=tag.document.body.scrollHeight"></iframe>
-->
</body>
</html>

由 beat 发表于 上午05点14分 | 回复 (0)

iframe自适应高度解决方法

<html>

<head><title>Test IFrame</title>
</head>
<body>
<Iframe name=tag align=center width="100%" src="http://www.nkstars.org/beat/" scrolling="no" frameborder="0" onload="this.height=tag.document.body.scrollHeight"></iframe>
</body>
</html>

由 beat 发表于 上午05点05分 | 回复 (0)

使用minidom来处理XML的示例

一.XML的读取.

在 NewEdit 中有代码片段的功能,代码片段分为片段的分类和片段的内容。在缺省情况下都是用XML格式保存的。下面我讲述一下,如何使用minidom来读取和保存XML文件。

下面是片段分类的一个示例文件--catalog.xml

<?xml version="1.0" encoding="utf-8"?>
<catalog>
<maxid>4</maxid>
<item id="1">
<caption>Python</caption>
<item id="4">
<caption>测试</caption>
</item>
</item>
<item id="2">
<caption>Zope</caption>
</item>
</catalog>

分类是树状结构,显示出来可能为:

Python
测试
Zope

先简单介绍一下XML的知识,如果你已经知道了可以跳过去。

1. XML文档的编码

此XML文档的编码为utf-8,因此你看到的“测试”其实是UTF-8编码。在XML文档的处理中都是使用UTF-8编码进行的,因此,如果你不写明encoding的话,都是认为文件是UTF-8编码的。在Python中,好象只支持几种编码,象我们常用的GB2312码就不支持,因此建议大家在处理XML时使用UTF-8编码。

2. XML文档的结构

XML文档有XML头信息和XML信息体。头信息如:

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

它表明了此XML文档所用的版本,编码方式。有些复杂的还有一些文档类型的定义(DOCTYPE),用于定义此XML文档所用的DTD或Schema和一些实体的定义。这里并没有用到,而且我也不是专家,就不再细说了。

XML信息体是由树状元素组成。每个XML文档都有一个文档元素,也就是树的根元素,所有其它的元素和内容都包含在根元素中。

3. DOM

DOM是Document Object Model的简称,它是以对象树来表示一个XML文档的方法,使用它的好处就是你可以非常灵活的在对象中进行遍历。

4. 元素和结点

元素就是标记,它是成对出现的。XML文档就是由元素组成的,但元素与元素之间可以有文本,元素的内容也是文本。在minidom中有许多的结点,元素也属于结点的一种,它不是叶子结点,即它存在子结点;还存在一些叶子结点,如文本结点,它下面不再有子结点。

象catalog.xml中,文档元素是catalog,它下面有两种元素:maxid和item。maxid用来表示当前最大的item的id值。每一个item都有一个id属性,id属性是唯一的,在 NewEdit 中用来生成每个分类所对应的代码片段的XML文档名,因此不能重复,而且它是一个递增的值。item元素有一个caption子元素,用来表示此分类项的名称,它还可以包含item元素。这样,就定义了一个树状XML结构,下面让我们看一看如果把它们读出来。


一、得到dom对象

>>> import xml.dom.minidom
>>> dom = xml.dom.minidom.parse('d:/catalog.xml')

这样我们得到了一个dom对象,它的第一个元素应该是catalog。

二、得到文档元素对象

>>> root = dom.documentElement

这样我们得到了根元素(catalog)。

三、结点属性

每一个结点都有它的nodeName,nodeValue,nodeType属性。nodeName为结点名字。

>>> root.nodeName
u'catalog'

nodeValue是结点的值,只对文本结点有效。nodeType是结点的类型,现在有以下几种:

'ATTRIBUTE_NODE'
'CDATA_SECTION_NODE'
'COMMENT_NODE'
'DOCUMENT_FRAGMENT_NODE'
'DOCUMENT_NODE'
'DOCUMENT_TYPE_NODE'
'ELEMENT_NODE'
'ENTITY_NODE'
'ENTITY_REFERENCE_NODE'
'NOTATION_NODE'
'PROCESSING_INSTRUCTION_NODE'
'TEXT_NODE'

这些结点通过名字很好理解。catalog是ELEMENT_NODE类型。

>>> root.nodeType
1
>>> root.ELEMENT_NODE
1

四、子元素、子结点的访问

访问子元素、子结点的方法很多,对于知道元素名字的子元素,可以使用getElementsByTagName方法,如读取maxid子元素:

>>> root.getElementsByTagName('maxid')
[<DOM Element: maxid at 0xb6d0a8>]

这样返回一个列表,由于我们的例子中maxid只有一项,因此列表也只有一项。

如果想得到某个元素下的所有子结点(包括元素),可以使用childNodes属性:

>>> root.childNodes
[<DOM Text node "\n ">, <DOM Element: maxid at 0xb6d0a8>, <DOM Text node "\n ">, <DOM Element: item at 0xb6d918>, <DOM Text node "\n ">, <DOM Element: item at 0xb6de40>, <DOM Text node "\n ">, <DOM Element: item at 0xb6dfa8>, <DOM Text node "\n">]

可以看出所有两个标记间的内容都被视为文本结点。象每行后面的回车,都被看到文本结点。从上面的结果我们可以看出每个结点的类型,本例中有文本结点和元素结点;结点的名字(元素结点);结点的值(文本结点)。每个结点都是一个对象,不同的结点对象有不同的属性和方法,更详细的要参见文档。由于本例比较简单,只涉及文本结点和元素结点。

getElementsByTagName可以搜索当前元素的所有子元素,包括所有层次的子元素。childNodes只保存了当前元素的第一层子结点。

这样我们可以遍历childNodes来访问每一个结点,判断它的nodeType来得到不同的内容。如,打印出所有元素的名字:

>>> for node in root.childNodes:
if node.nodeType == node.ELEMENT_NODE:
print node.nodeName

maxid
item
item

对于文本结点,想得到它的文本内容可以使用: .data属性。

对于简单的元素,如:<caption>Python</caption>,我们可以编写这样一个函数来得到它的内容(这里为Python)。

def getTagText(root, tag):
node = root.getElementsByTagName(tag)[0]
rc = ""
for node in node.childNodes:
if node.nodeType in ( node.TEXT_NODE, node.CDATA_SECTION_NODE):
rc = rc + node.data
return rc

这个函数只处理找到的第一个符合的子元素。它会将符合的第一个子元素中的所有文本结点拼在一起。当nodeType为文本类结点时,node.data为文本的内容。如果我们考查一下元素caption,我们可能看到:

[<DOM Text node "Python">]

说明caption元素只有一个文本结点。

如果一个元素有属性,那么可以使用getAttribute方法,如:

>>> itemlist = root.getElementsByTagName('item')
>>> item = itemlist[0]
>>> item.getAttribute('id')
u'1'

这样就得到了第一个item元素的属性值。

下面让我们简单地小结一下如何使用minidom来读取XML中的信息

1. 导入xml.dom.minidom模块,生成dom对象
2. 得到文档对象(根对象)
3. 通过getElementsByTagName()方法和childNodes属性(还有其它一些方法和属性)找到要处理的元素
4. 取得元素下文本结点的内容


二.写入.


下面我来演示一下如何从无到有生成象catalog.xml一样的XML文件。

一、生成dom对象

>>> import xml.dom.minidom
>>> impl = xml.dom.minidom.getDOMImplementation()
>>> dom = impl.createDocument(None, 'catalog', None)

这样就生成了一个空的dom对象。其中catalog为文档元素名,即根元素名。

二、显示生成的XML内容

每一个dom结点对象(包括dom对象本身)都有输出XML内容的方法,如:toxml(), toprettyxml()

toxml()输出紧凑格式的XML文本,如:

<catalog><item>test</item><item>test</item></catalog>

toprettyxml()输出美化后的XML文本,如:

<catalog>
<item>
test
</item>
<item>
test
</item>
</catalog>

可以看出,它是将每个结点后面都加入了回车符,并且自动处理缩近。但对于每一个元素,如果元素只有文本内容,则我希望元素的tag与文本是在一起的,如:

<item>test</item>

而不想是分开的格式,但minidom本身是不支持这样的处理。关于如何实现形如:

<catalog>
<item>test</item>
<item>test</item>
</catalog>

这样的XML格式,后面我们再说。

三、生成各种结点对象

dom对象拥有各种生成结点的方法,下面列出文本结点,CDATA结点和元素结点的生成过程。

1. 文本结点的生成

>>> text=dom.createTextNode('test')
test

要注意的是,在生成结点时,minidom并不对文本字符进行检查,象文本中如果出现了'<','&'之类的字符,应该转换为相应的实体符号'<','&'才可以,这里没有做这个处理。

2. CDATA结点的生成

>>> data = dom.createCDATASection('aaaaaa\nbbbbbb')
>>> data.toxml()
'<![CDATA[aaaaaa\nbbbbbb]]>'

CDATA是用于包括大块文本,同时可以不用转换'<','&'字符的标记,它是用<![CDATA[文本]]>来包括的。但文本中不可以有"]]>"这样的串存在。生成结点时minidom不作这些检查,只有当你输出时才有可能发现有错。

3. 元素结点的生成

>>> item = dom.createElement('caption')
>>> item.toxml()
'<caption/>'

对于象元素这样的结点,生成的元素结点其实是一个空元素,即不包含任何文本,如果要包含文本或其它的元素,我们需要使用appendChild()或insertBefore()之类的方法将子结点加就到元素结点中。如将上面生成的text结点加入到caption元素结点中:

>>> item.appendChild(text)
<DOM Text node "test">
>>> item.toxml()
'<caption>test</caption>'

使用元素对象的setAttribute()方法可以向元素中加入属性,如:

>>> item.setAttribute('id', 'idvalue')
>>> item.toxml()
'<caption id="idvalue">test</caption>'

四、生成dom对象树

我们有了dom对象,又知道了如何生成各种结点,包括叶子结点(不包含其它结点的结点,如文本结点)和非叶子结点(包含其它结点的结点,如元素结点)的生成,然后就需要利用结点对象本身的appendChild()或insertBefore()方法将各个结点根据在树中的位置连起来,串成一棵树。最后要串到文档结点上,即根结点上。如一个完整的示例为:

>>> import xml.dom.minidom
>>> impl = xml.dom.minidom.getDOMImplementation()
>>> dom = impl.createDocument(None, 'catalog', None)
>>> root = dom.documentElement
>>> item = dom.createElement('item')
>>> text = dom.createTextNode('test')
>>> item.appendChild(text)
<DOM Text node "test">
>>> root.appendChild(item)
<DOM Element: item at 0xb9cf80>
>>> print root.toxml()
<catalog><item>test</item></catalog>

五、简单生成元素结点的函数

下面是我写的一个小函数,用于简单的生成类似于:

<caption>test</caption>

或形如:

<item><![CDATA[test]]></item>

的元素结点

1 def makeEasyTag(dom, tagname, value, type='text'):
2 tag = dom.createElement(tagname)
3 if value.find(']]>') > -1:
4 type = 'text'
5 if type == 'text':
6 value = value.replace('&', '&')
7 value = value.replace('<', '& lt;')
8 text = dom.createTextNode(value)
9 elif type == 'cdata':
10 text = dom.createCDATASection(value)
11 tag.appendChild(text)
12 return tag

参数说明:

dom为dom对象
tagname为要生成元素的名字,如'item'
value为其文本内容,可以为多行
type为文本结点的格式,'text'为一般Text结点,'cdata'为CDATA结点
函数处理说明:

首先创建元素结点
查找文本内容是否有']]>',如果找到,则此文本结点只可以是Text结点
如果结点类型为'text',则对文本内容中的'<'替换为'<','&'替换为'&',再生成文本结点
如果结点类型为'cdata',则生成CDATA结点
将生成的文本结点追加到元素结点上
因此这个小函数可以自动地处理字符转化及避免CDATA结点中出现']]>'串。

上面生成'item'结点的语句可以改为:

>>> item = makeEasyTag(dom, 'item', 'test')
>>> item.toxml()
'<item>test</item>'

六、写入到XML文件中

dom对象树已经生成好了,我们可以调用dom的writexml()方法来将内容写入文件中。writexml()方法语法格式为:

writexml(writer, indent, addindent, newl, encoding)

writer是文件对象
indent是每个tag前填充的字符,如:' ',则表示每个tag前有两个空格
addindent是每个子结点的缩近字符
newl是每个tag后填充的字符,如:'\n',则表示每个tag后面有一个回车
encoding是生成的XML信息头中的encoding属性值,在输出时minidom并不真正进行编码的处理,如果你保存的文本内容中有汉字,则需要自已进行编码转换。
writexml方法是除了writer参数必须要有外,其余可以省略。下面给出一个文本内容有汉字的示例:

1 >>> import xml.dom.minidom
2 >>> impl = xml.dom.minidom.getDOMImplementation()
3 >>> dom = impl.createDocument(None, 'catalog', None)
4 >>> root = dom.documentElement
5 >>> text = unicode('汉字示例', 'cp936')
6 >>> item = makeEasyTag(dom, 'item', text)
7 >>> root.appendChild(item)
8 <DOM Element: item at 0xb9ceb8>
9 >>> root.toxml()
10 u'<catalog><item>\u6c49\u5b57\u793a\u4f8b</item></catalog>'
11 >>> f=file('d:/test.xml', 'w')
12 >>> import codecs
13 >>> writer = codecs.lookup('utf-8')[3](f)
14 >>> dom.writexml(writer, encoding='utf-8')
15 >>> writer.close()

5行 因为XML处理时内部使用Unicode编码,因此象汉字首先要转成Unicode,如果你不做这一步minicode并不检查,并且保存时可能不会出错。但读取时可能会出错。
12-13行 生成UTF-8编码的写入流对象,这样在保存时会自动将Unicode转换成UTF-8编码。

这样写XML文件就完成了。

三.美化.

对于dom对象的writexml()方法,虽然可以控制一些格式上的输出,但结果并不让人满意。比如我想实现:

<catalog>
<item>test</item>
<item>test</item>
</catalog>

而不是:

<catalog>
<item>
test
</item>
<item>
test
</item>
</catalog>

如果是象下面的输出结果我无法区分原来文本中是否带有空白,而上一种结果则不存在这一问题。好在我在wxPython自带的XML资源编辑器(xred)发现了美化的代码。代码如下:

1 def Indent(dom, node, indent = 0):
2 # Copy child list because it will change soon
3 children = node.childNodes[:]
4 # Main node doesn't need to be indented
5 if indent:
6 text = dom.createTextNode('\n' + '\t' * indent)
7 node.parentNode.insertBefore(text, node)
8 if children:
9 # Append newline after last child, except for text nodes
10 if children[-1].nodeType == node.ELEMENT_NODE:
11 text = dom.createTextNode('\n' + '\t' * indent)
12 node.appendChild(text)
13 # Indent children which are elements
14 for n in children:
15 if n.nodeType == node.ELEMENT_NODE:
16 Indent(dom, n, indent + 1)

参数说明:

dom为dom对象
node为要处理的元素结点
indent指明缩近的层数

函数说明:

Indent是一个递归函数,当一个结点有子元素时进行递归处理。主要是解决子元素的换行和缩近的处理。这里缩近是写死的,每一级缩近使用一个制表符。如果你愿意可以改为你想要的内容。就是把函数中的'\t'换替一下。或干脆写成一个全局变量,或参数以后改起来可能要容易的多。不过在 NewEdit 中,这样的处理足够了,就没有做这些工作。

Indent基本的想法就是递归遍历所有子结点,在所有需要加入回车和缩近的地方插入相应的文本结点。这样再使用writexml()输出时就是缩近好了的。具体程序不再细说,直接用就行了。

但这里要注意的是:

Indent()要修改原dom对象,因此在调用它之前最好先复制一个临时dom对象,使用完毕后再清除这个临时dom对象即可。下面是详细的调用过程:

1 domcopy = dom.cloneNode(True)
2 Indent(domcopy, domcopy.documentElement)
3 f = file(xmlfile, 'wb')
4 writer = codecs.lookup('utf-8')[3](f)
5 domcopy.writexml(writer, encoding = 'utf-8')
6 domcopy.unlink()

1行 克隆一个dom对象
2行 进行缩近处理
3-4行 进行UTF-8编码处理
5行 生成XML文件
6行 清除dom对象的内容

经过这番处理之后,你的XML文档应该好看多了。

由 beat 发表于 上午03点04分 | 回复 (0)

2006年09月01日 星期五

基本的xml解析在Python的流程

我准备解析下面这个文档(关于xml的知识可以到http://www.w3.org上查看相关的Recommendations):
代码

<catalog>;
  <book isbn="1-56592-724-9">;
    <title>;The Cathedral & the Bazaar</title>;
    <author>;Eric S. Raymond</author>;
  </book>;
  <book isbn="1-56592-051-1">;
    <title>;Making TeX Work</title>;
    <author>;Norman Walsh</author>;
  </book>;
  <!-- imagine more entries here... -->;
</catalog>;

Python的标准模块里包含了xml 处理的module。我们这次用的是xml.dom.minidom,一个迷你版的DOM API
代码:

#! /usr/bin/python

import xml.dom.minidom
from xml.dom.minidom import Node

doc = xml.dom.minidom.parse("books.xml")

mapping = {}
for node in doc.getElementsByTagName("book"):
    isbn = node.getAttribute("isbn")
    L = node.getElementsByTagName("title")
    for node2 in L:
        title = ""
        for node3 in node2.childNodes:
            if node3.nodeType == Node.TEXT_NODE:
                title += node3.data
                mapping[isbn] = title
                # mapping now has the same value as in the SAX example:
                print(mapping)

通过这个程序,可以看到解析xml的文件的过程, minidom.parse返回的就是一个xml.dom.Document类型的实例。其实就是DOM中定义的Document了。通常的DOM的操作都是通过这个类来完成,比如例子中的建立ISBN和书名的对应关系表。对DOM的API,大家可以查看相关的文档。

同时,这次引入了一个新的控制结构,就是for-loop。这个和C和Java的for循环有些区别(Java在5.0中也引入了这种循环)。这个循环是for-each-in格式的。而不是传统的以初始值,步进值和中止条件控制循环过程的。

由 beat 发表于 下午11点12分 | 回复 (0)

重温 Python 的 XML 工具

转载自:http://www.uplinux.com/www/dev/01/11.shtml

David Mertz 博士(mertz@gnosis.cx)
Phenomenological unifier,Gnosis Software, Inc.


David Mertz 创作的可爱的 Python 的第一、第二部分概述了在 Python 中使用 XML。然而,在那些最初的文章出现后,Python 中的 XML 工具有了很大的发展。不幸的是,这些改进中的大多数并不向后兼容。在这个特别部分中,重温了作者先前对 XML 工具的讨论,并提供最新的代码示例。


在许多情况下,Python 是使用 XML 文档的理想语言。像 Perl、REBOL、REXX 和 TCL 一样,它是一种灵活的脚本语言,并且有强大的文本操作能力。而且,除了对多数类型的文本文件(或流文件)编码外,XML 文档还编码大量复杂的数据结构。


继续在 Python 2.0 中对 XML 的支持
文本处理中常见的“读取几行,并将它们与一些规则表达式比较”样式通常不能很好地适合对 XML 进行彻底语法分析和处理。幸好,Python(与大多数其它语言相比)不仅有处理复杂数据结构的直接方法(通常使用类和属性),还有一系列 XML 相关的模块可以帮助语法分析、处理和生成 XML。


XML-SIG (专门兴趣组)的成员为维护 Python 一系列 XML 工具做了许多工作。与其它 Python 专门兴趣组一样,XML-SIG 要维护邮件发送列表、列表档案、有用的参考大全、文档、标准包和其它资源(请参阅本文后的参考资料)。


从 Python 2.0 开始,Python 在其标准发行版中包括大多数 XML-SIG 项目。最新的 XML-SIG 包可能包含一些 Python 标准发行版中没有的“极端先进”特性,但出于面向绝大多数人的目的 -- 包括本文中的讨论 -- Python 2.0 的 XML 支持将是您感兴趣的。幸运的是,早期 Python 版本对 xmllib 的基本支持在 Python 2.0+ 下有了很大进步。目前,Python 用户能正常的选择 DOMSAXexpat 技术来处理 XML (使用其他编程语言的 XML 开发人员将会意识到这些)。


模块:xmllib
xmllib 是一个非验证的低级语法分析器。应用程序员使用的 xmllib 可以覆盖 XMLParser 类,并提供处理文档元素(如特定或类属标记,或字符实体)的方法。从 Python 1.5x 到 Python 2.0+ 以来,xmllib 的使用方法并没变化;在绝大多数情况下更好的选择是使用 SAX 技术,它也是种面向流的技术,对语言和开发者来说更为标准。


本文中的示例与原来专栏中的相同:包括一个叫做 quotations.dtd 的 DTD 以及这个 DTD 的文档 sample.xml (请参阅参考资料,以获取本文中提到的文件的档案)。以下的代码显示了 sample.xml 中每段引言的前几行,并生成了非常简单的未知标记和实体的 ASCII 指示符。经过分析的文本作为连续流来处理,所使用的任何累加器都由程序员负责(如标记中的字符串 (#PCDATA),或所遇到的标记的列表或词典)。


清单 1: try_xmllib.py





import xmllib, string

classQuotationParser(xmllib.XMLParser):
"""Crude xmllib extractor for quotations.dtd document"""
def__init__(self):
xmllib.XMLParser.__init__(self)
self.thisquote = '' # quotation accumulator
defhandle_data(self, data):
self.thisquote = self.thisquote + data
defsyntax_error(self, message):
pass
defstart_quotations(self, attrs): # top level tag
print '--- Begin Document ---'
defstart_quotation(self, attrs):
print 'QUOTATION:'
defend_quotation(self):
print string.join(string.split(self.thisquote[:230]))+'...',
print '('+str(len(self.thisquote))+' bytes)'
self.thisquote = ''
defunknown_starttag(self, tag, attrs):
self.thisquote = self.thisquote + '{'
defunknown_endtag(self, tag):
self.thisquote = self.thisquote + '}'
defunknown_charref(self, ref):
self.thisquote = self.thisquote + '?'
defunknown_entityref(self, ref):
self.thisquote = self.thisquote + '#'

if __name__ == '__main__':
parser = QuotationParser()
for c in open("sample.xml").read():
parser.feed(c)
parser.close()




验证
您可能需要展望标准 XML 支持的未来的原因是,在进行语法分析的同时需要进行验证。不幸的是,标准 Python 2.0 XML 包并不包括验证型语法分析器。


xmlproc 是 python 原有的语法分析器,它执行几乎完整的验证。如果需要验证型语法分析器, xmlproc 是 Python 当前唯一的选择。而且,xmlproc 提供其它语法分析器所不具备的各种高级和测试接口。


选择一种语法分析器
如果决定使用 XML 的简单 API (SAX) -- 它应该用于复杂的事物,因为其它大部分工具都是在它的基础上建立的 -- 将为您完成许多语法分析器的分类工作。xml.sax 模块包含一个自动选择“最佳”语法分析器的设施。在标准 Python 2.0 安装中,唯一能选择的语法分析器是 expat,它是种 C 语言编写的快速扩展。然而,也可以在 $PYTHONLIB/xml/parsers 下安装另一个语法分析器,以备选择。设置语法分析器很简单:


清单 2: Python 选择最佳语法分析器的语句





import xml.sax
parser = xml.sax.make_parser()




您还可以通过传递参数来选择特定的语法分析器;但考虑到可移植性 -- 也为了对今后更好的语法分析器的向上兼容性 -- 最佳方法是使用 make_parser() 来完成工作。


您可以直接导入 xml.parsers.expat。如果这样做,您就能获得 SAX 界面并不提供的一些特殊技巧。这样,xml.parsers.expat 与 SAX 相比有些“低级”。但 SAX 技术非常标准,对面向流的处理也非常好;大多数情况下 SAX 的级别正合适。通常情况下,由于 make_parser() 函数已经能获得 expat 提供的性能,因此纯速度的差异很小。


什么是 SAX
考虑到背景因素,回答什么是 SAX 的较好答案是:


SAX (XML 的简单 API)是 XML 语法分析器的公用语法分析器接口。它允许应用程序作者编写使用 XML 语法分析器的应用程序,但是它却独立于所使用的语法分析器。(将它看作 XML 的 JDBC。)(Lars Marius Garshol,SAX for Python)

SAX -- 如同它提供的语法分析器模块的 API -- 基本上是一个 XML 文档的顺序处理器。使用它的方法与 xmllib 示例极其相似,但更加抽象。应用程序员将定义一个 handler 类,而不是语法分析器类,该 handler 类能注册到任何所使用的语法分析器中。必须定义 4 个 SAX 接口(每个接口都有几个方法):DocumentHandler、DTDHandler、EntityResolver 和 ErrorHandler。创建语法分析器除非被覆盖,否则它还连接默认接口。这些代码执行与 xmllib 示例相同的任务:


清单 3: try_sax.py





"Simple SAX example, updated for Python 2.0+"
import string
import xml.sax
from xml.sax.handler import *

classQuotationHandler(ContentHandler):
"""Crude extractor for quotations.dtd compliant XML document"""
def__init__(self):
self.in_quote = 0
self.thisquote = ''
defstartDocument(self):
print '--- Begin Document ---'
defstartElement(self, name, attrs):
if name == 'quotation':
print 'QUOTATION:'
self.in_quote = 1
else:
self.thisquote = self.thisquote + '{'
defendElement(self, name):
if name == 'quotation':
print string.join(string.split(self.thisquote[:230]))+'...',
print '('+str(len(self.thisquote))+' bytes)'
self.thisquote = ''
self.in_quote = 0
else:
self.thisquote = self.thisquote + '}'
defcharacters(self, ch):
if self.in_quote:
self.thisquote = self.thisquote + ch

if __name__ == '__main__':
parser = xml.sax.make_parser()
handler = QuotationHandler()
parser.setContentHandler(handler)
parser.parse("sample.xml")




xmllib 相比,上述示例中要注意两件小事:.parse() 方法处理整个流或字符串,所以不必为语法分析器创建循环;.parse() 同样能灵活地接收一个文件名、一个文件对象,或是众多的类文件对象(一些具有 .read() 方式)。


包:DOM
DOM 是一种 XML 文档的高级树型表示。该模型并非只针对 Python,而是一种普通 XML 模型(请参阅参考资料以获取进一步信息)。Python 的 DOM 包是基于 SAX 构建的,并且包括在 Python 2.0 的标准 XML 支持里。由于篇幅所限,没有将代码示例加到本文中,但在 XML-SIG 的 "Python/XML HOWTO" 中给出了一个极好的总体描述:


文档对象模型为 XML 文档指定了树型表示。顶级文档实例是树的根,它只有一个子代,即顶级元素实例;这个元素有表示内容和子元素的子节点,他们也可以有子代,以此类推。定义的函数允许随意遍历结果树,访问元素和属性值,插入和删除节点,以及将树转换回 XML。



DOM 可以用于修改 XML 文档,因为可以创建一棵 DOM 树,通过添加新节点和来回移动子树来修改这棵树,然后生成一个新的 XML 文档作为输出。您也可以自己构造一棵 DOM 树,然后将它转换成 XML;用这种方法生成 XML 输出比仅将 <tag1>...</tag1> 写入文件的方法更灵活。



使用 xml.dom 模块的语法与早期的文章相比有了一些变动。Python 2.0 中自带的 DOM 实现被称为 xml.dom.minidom,并提供轻量级和小型版本的 DOM。显然,完整的 XML-SIG 的 DOM 中有些试验性的特性并未被放入 xml.dom.minidom 中,但大家并不会注意到这一点。


生成 DOM 对象很简单;只需:


清单 4: 在 XML 文件中创建 Python DOM 对象





from xml.dom.minidom import parse, parseString
dom1 = parse('mydata.xml') # parse an XML file by name




使用 DOM 对象是种非常直接的 OOP 模式的工作。然而,经常在无法立刻简单区分的层级(除了循环列举)中碰到许多类似清单的属性。例如,以下是一段普通的 DOM Python 代码片断:


清单 5: 通过 Python DOM 节点对象的迭代





for node in dom_node.childNodes:
if node.nodeName == '#text': # PCDATA is a kind of node,
PCDATA = node.nodeValue # but not a new subtag
elif node.nodeName == 'spam':
spam_node_list.append(node) # Create list of <spam> nodes




Python 标准说明文档中有一些更详细的 DOM 示例。我的早期文章中有关使用 DOM 对象的示例(请参阅参考资料)指出的方向仍然是正确的,但是文章发布后至今,一些方法和属性名称以更改,因此请查阅一下 Python 的说明文档。


模块: pyxie
pyxie 模块是在 Python 标准 XML 支持之上构建的,它为 XML 文档提供了附加的高级接口。pyxie 将完成两项基本操作:它将 XML 文档转换成一种更易于进行语法分析的基于行的格式;并且它提供了将 XML 文档当作可操作树处理的方法。pyxie 所使用的基于行的 PYX 格式是不受语言限制的,其工具适用于几种语言。总之,文档的 PYX 表示与其 XML 表示相比,更易于使用常见的基于行的文本处理工具进行处理,如 grep、sed、awk、bash、perl,或标准 python 模块,如 stringre。根据结果,从 XML 转换到 PYX 可能节省许多工作。


pyxie 将 XML 文档当作树处理的概念与 DOM 中的思路相似。由于 DOM 标准得到许多编程语言的广泛支持,那么如果 XML 文档的树型表示是必需的,大多数程序员会使用 DOM 标准而非 pyxie


更多模块:xml_picklexml_objectify
我自行开发了处理 XML 的高级模块,称为 xml_picklexml_objectify。我还在其它地方写过许多类似模块(请参阅参考资料),在此不必做过多的介绍。当你“用 Python 思考”而不是“用 XML 思考”时,这些模块非常有用。特别是 xml_objectify 自身对程序员隐藏了几乎所有的 XML 线索,使您在程序中充分使用 Python “原始”对象。实际的 XML 数据格式几乎被抽象得不可见。同样,xml_pickle 使 Python 程序员以“原始” Python 对象开始,该对象的数据可以来源于任何源代码,然后把它们(连续地)放入其他用户以后可能需要的 XML 格式。


参考资料





由 beat 发表于 下午09点36分 | 回复 (0)