转载:如何使用python将文本文件转化为XML文件

http://www.linuxforum.net/forum/printthread.php?Cat=&Board=python&main=569087&type=thread
zhyeye
(stranger)
05-07-21 21:44
请教前辈们,如何使用python将文本文件转化为XML文件???

我是新手,现在有一个文本文件,想要把里边的数据转化成XML文件格式,可是怎么都弄不好,请前辈帮忙,感激不尽!!
文本文件如下;(123.txt)
xiaoyu female 20 english 80 maths 88 chinese 92 song 44 yang 45 beijing
dawei male 21 english 85 maths 94 chinese 89 he 46 zhang 48 shanghai
......
......
想要生成如下xml文件;
<?xml version = "1.0"?>
<?xml:stylesheet type = "text/xsl"
href = "xszt.xsl"?>
<xueshengzhuangtai>
<number1>
<name>xiaoyu</name>
<gender>female</gender>
<age>20</age>
<result_exam>
<course>english</course>
<score>80</score>
<course>maths</course>
<score>88</score>
<course>chinese</course>
<score>92</score>
</result_exam>
<family>
<mother>song</mother>
<age>44</age>
<father>yang</father>
<age>45</age>
</family>
<city>beijing</city>
</number1>
.
.
.
.
</xueshengzhuangtai>
我试了好多次,但是都只能生成一级结构,就是这样的;
<number1>
<name>xiaoyu</name>
<gender>female</gender>
<age>20</age>
<result_exam>
english 80 maths 88 chinese 92
</result_exam>
<family>song 44 yang 45</family>
<city>beijing</city>
</number1>

请求帮忙,多谢多谢!


limodou版主
(Pooh-Bah)
05-07-21 22:34
Re: 请教前辈们,如何使用python将文本文件转化为XML文件???

程序贴出来看一看。

zhyeye
(stranger)
05-07-21 23:12
Re: 请教前辈们,如何使用python将文本文件转化为XML文件???

我把原文件改成这样了,(为了区分字段)
xiaoyu female 20 english,80 maths,88 chinese,92 song;44;yang;45 beijing
dawei male 21 english,85 maths,94 chinese,89 he;46 zhang;48 shanghai

程序如下:


import sys

print "Content-type:text/xml/n"



print """<?xml version = "1.0"?>

<?xml:stylesheet type = "text/xsl"

href = "xszt.xsl"?>"""



#open data file

try:

file = open( "xszt.txt","r" )

except IOError:

sys.exit( "Error opening file" )



print "<xueshengzhuangtai>" #write root element



#list of tuples:(special character,entity reference)

replaceList = [ ( "&", "&amp;" ),

( "<", "&lt;" ),

( ">", "&gt;" ),

( '"', "&quot;" ),

( "'", "&apos;" ) ]



#replace special characters with entity reference

for currentLine in file.readlines():



for oldValue, newValue in replaceList:

currentLine = currentLine.replace( oldValue, newValue )



#extract element

name, gender, age, result_exam, family, city = currentLine.split( " " )

city = city.strip() #remove carriage return



#write xueshengzhuangtai element

print """ <xueshengzhuangtai>

<Name>%s</Name>

<gender>%s</gender>

<age>%s</age>

<result_exam>%s</result_exam>

<family>%s</family>

<city>%s</city>

</xueshengzhuangtai>""" % ( name, gender, age, result_exam, family, city )



for result_exam in file.readlines():



for oldValue, newValue in replaceList:

currentLine = currentLine.replace( oldValue, newValue )



course, score = currentLine.split( ", " )

score = score.strip() #remove carriage return



#write result_exam element

print """ <result_exam>

<course>%s</course>

<score >%s</score >

</result_exam>""" % ( course, score )



for family in file.readlines():



for oldValue, newValue in replaceList:

currentLine = currentLine.replace( oldValue, newValue )



mother, age, father, age = currentLine.split( ";" )

age = age.strip() #remove carriage return



#write family element

print """ <family>

<mother>%s</mother>

<age>%s</age>

<father>%s</father>

<age>%s</age>

</family>""" % ( mother, age, father, age )



file.close()



print "</contacts>"



zhyeye
(stranger)
05-07-21 23:20
Re: 请教前辈们,如何使用python将文本文件转化为XML文件???

我刚开始学,还不懂得怎么用,希望limodou大哥哥不吝赐教,多谢了!

limodou版主
(Pooh-Bah)
05-07-22 09:05
Re: 请教前辈们,如何使用python将文本文件转化为XML文件???

file.readlines() 怎么会在循环中多次出现?
转换 <, > 之类的字符可以使用cgi.escape()方法
解析文本文件,与生成结果不是很清晰,建议先将文本的解析独立出来,然后将解析出来的结果再加工成xml格式。生成xml的方式就非常多了:

1.使用xml包,利用dom对象
2.使用模板
3.自已写简单的替换格式,如:

print "%(name)s %(age)d" % {'name':'test', 'age':14}

再改一改


zhyeye
(stranger)
05-07-22 16:29
Re: 请教前辈们,如何使用python将文本文件转化为XML文件???

不好意思,limdou大哥,我还是不太明白该怎么去做,是说这里不能永元组吗?我就只会一点python,但是老板要我完成这个任务,所以可不可以请您帮忙改一下,或者您给我推荐一下什么地方有类似的例子。
多谢了!

limodou版主
(Pooh-Bah)
05-07-22 17:39
Re: 请教前辈们,如何使用python将文本文件转化为XML文件???

如果是为了完成任务就使用你原来的方法就可以,但你的逻辑上有问题还是需要改一改,正如我说的,你有多个readlines()不知道是为什么?

zhyeye
(stranger)
05-07-22 18:11
Re: 请教前辈们,如何使用python将文本文件转化为XML文件???

我用多个readlines()的本意是想要读出二级的数据,生成:
<result_exam>
<course>english</course>
<score>80</score>
<course>maths</course>
<score>88</score>
<course>chinese</course>
<score>92</score>
</result_exam>
<family>
<mother>song</mother>
<age>44</age>
<father>yang</father>
<age>45</age>
</family>
但是下面两个重复的readlines()这部分代码根本就不运行,我也不知道该怎么改,所以请求您帮忙。
多谢!

limodou版主
(Pooh-Bah)
05-07-22 21:30
Re: 请教前辈们,如何使用python将文本文件转化为XML文件???

我按照你的第一个贴子写了一个程序,
因为那个处理起来更简单


header = """<?xml version = "1.0"?>

<?xml:stylesheet type = "text/xsl"

href = "xszt.xsl"?>

<xueshengzhuangtai>"""



body="""<number1>

<name>%(name)s</name>

<gender>%(sex)s</gender>

<age>%(age)s</age>

<result_exam>

<course>%(en_course)s</course>

<score>%(en_score)s</score>

<course>%(math_course)s</course>

<score>%(math_score)s</score>

<course>%(ch_course)s</course>

<score>%(ch_score)s</score>

</result_exam>

<family>

<mother>%(mother)s</mother>

<age>%(mother_age)s</age>

<father>%(father)s</father>

<age>%(father_age)s</age>

</family>

<city>%(liveing)s</city>

</number1>"""



footer="""</xueshengzhuangtai>"""



def deal_body():

for line in file('d:/a.txt'):

(name, sex, age, en_course, en_score, math_course, math_score,

ch_course, ch_score, mother, mother_age, father, father_age, liveing) = line.split()

print body % locals()



if __name__ == '__main__':

print header

deal_body()

print footer


为什么按第一个贴子处理更简单呢?因为对于xml报文来说是分层的,但对于生成结果却是不需要考虑的,只要把相应的xml文本看成模块,进行一维替换即可。

zhyeye
(stranger)
05-07-25 17:21
辛苦您了,limodou大哥!

多谢limodou大哥,帮我解决了一个难题,只是如果文档中的考试科目和考试成绩一项如果不固定的话这个程序好像就不适用了,比如;
xiaoyu female 20 english 80 maths 88 chinese 92 song 44 yang 45 beijing (考了3门课)
xiaoming male 20 english 82 maths 84 huang 44 li 45 beijing (考了2门课)
dawei male 21 english 85 maths 94 chinese 89 he 46 zhang 48 shanghai (考了3门课)
xiaoxiao male 20 geography 87 lv 44 wang 45 beijing (考了1门课)
xiaohong female 21 english 88 maths 84 chinese 94 biology 86 history 78 hu 46 han 48 shanghai (考了5门课)
feifei male 21 hu 46 han 48 shanghai (没有考试成绩)
如果这样的话该怎么解决?limodou大哥哥,我真的很不好意思,一而再再而三的问您,我第一次没有仔细看完那个txt文档,没有注意到后面后面考试成绩和考试科目的变化,给您添麻烦了,希望您能再帮帮忙!多谢了!


passworld
(enthusiast)
05-07-25 19:09
Re: 辛苦您了,limodou大哥!

你这样科目混排是挺难读得,自己给自己出难题。还是把所有科目用分号分开,其他的用空格分开比较容易。


#!/usr/bin/python



line = "xiaoyu female 20 english 80 maths 88 chinese 92 song 44 yang 45 beijing"



def parse_line(line):

items = line.split()

rawgrade = items[3:-5]

grade = dict(zip(rawgrade[::2], rawgrade[1::2]))

return items[:3], items[-5:], grade



items = parse_line(line)

print items

# vim:ts=8:sw=4:expandtab




limodou版主
(Pooh-Bah)
05-07-25 20:54
Re: 辛苦您了,limodou大哥!

如果这样的话你的模板就有问题了。因为最后面的父母信息怎么不见了。你的原始数据是什么样的啊。

zhyeye
(stranger)
05-07-25 23:22
Re: 辛苦您了,limodou大哥!

原文件太长了,我就列举了一小部分;
Xiaoyu * female * 20 * english 80 maths 88 chinese 92 * song 44 yang 45 * Beijing * (考了3门课)
xiaoming * male * 20 * english 82 maths 84 * huang 44 li 45 * Beijing * (考了2门课)
dawei male * 21 * english 85 maths 94 chinese 89 * he 46 zhang 48 * shanghai * (考了3门课)
xiaoxiao * male * 20 * geography 87 * lv 44 wang 45 * Beijing * (考了1门课)
xiaohong * female * 21 * english 88 maths 84 chinese 94 biology 86 history 78 * hu 46 han 48 * shanghai * (考了5门课)
feifei * male * 21 * * hu 46 han 48 *shanghai * (没有考试成绩)
xiaoying * female * 20 * english 80 maths 86 geography 90 * li 48 *shanghai * (考了3门课)
……………
原文件中使用 * 来区分一级字段,<name>,<gender>,<age>, <result_exam>,<family>和<city>。如果某一字段为空,就是这样 * * 。
<result_exam>和<family>下有二级字段,二级字段以空格来区分,而且< result_exam>中学生参加考试的科目不确定,有的参加的多,有的参加的少,有的根本没有参加;<family>中有的是父母 两个人的信息,有的只有一个人的信息(所以就不区分是父亲还是母亲,直接用<parents>和<age>来表示)。

我本来想弄得简单一点,所以就用列了以前的例子,没想到却越弄越麻烦,真的是太麻烦您了,limodou大哥。
麻烦您再帮忙一下,不胜感激!

zhyeye
(stranger)
05-07-26 16:18
Re: 辛苦您了,limodou大哥!

不好意思,请您帮帮忙!
多谢了!

limodou版主
(Pooh-Bah)
05-07-26 16:30
Re: 辛苦您了,limodou大哥!

不过我不会把全部程序给你写完的,因为如果这样永远也学不
会python。
下面是我写的对于你的数据的一个解析程序:


for line in file('a.txt'):

v = [x.strip() for x in line.rstrip().split('*')][:-1]

name, sex, age, score, family, city = tuple(v)

if score:

s = score.split()

score = [(s[i], s[i+1]) for i in range(len(s)/2)]

else:

score = []

if family:

s = family.split()

family = [(s[i*2], s[i*2+1]) for i in range(len(s)/2)]

else:

family = []

print name, sex, age, score, family, city



它首先按*号进行分解。但因为你的数据每行最后有一个*号,
这样分解出来后会多一个空串,因此[:-1]就是将空串去掉。
这样,分解完毕后score和family可能为多条信息,个数不一
样。因此下面一个是对score的处理,一个是对family的处理。
对于score是将信息按空格拆分,然后两两组合成一个tuple。
最后返回为一个list,如果数据为空则为一个空list。family也是
如此。

根据你的数据得到下面的输出结果:

Xiaoyu female 20 [('english', '80'), ('80', 'maths'), ('maths', '88')] [('song', '44'), ('yang', '45')] Beijing
xiaoming male 20 [('english', '82'), ('82', 'maths')] [('huang', '44'), ('li', '45')] Beijing
dawei male 21 [('english', '85'), ('85', 'maths'), ('maths', '94')] [('he', '46'), ('zhang', '48')] shanghai
xiaoxiao male 20 [('geography', '87')] [('lv', '44'), ('wang', '45')] Beijing
xiaohong female 21 [('english', '88'), ('88', 'maths'), ('maths', '84'), ('84', 'chinese'), ('chinese', '94')] [('hu', '46'), ('han', '48')] shanghai
feifei male 21 [] [('hu', '46'), ('han', '48')] shanghai
xiaoying female 20 [('english', '80'), ('80', 'maths'), ('maths', '86')] [('li', '48')] shanghai

因此多项的为一个list,单项的就是一个字符。这样你结
合这样的结果再加上我以前贴出的程序自已合并一个生
成最终程序吧。

BTW:你的数据第三行有问题:dawei与male之间没有星号。

zhyeye
(stranger)
05-07-26 16:49
Re: 辛苦您了,limodou大哥!

多谢您,limodou大哥,我自再试试,多谢,多谢!

zhyeye
(stranger)
05-07-26 17:58
limodou大哥,程序有点问题

你这样使用元组之后就出现了一个问题,在score字段中总是会出现冗余的一组,而且每两组数据就会有一组冗余,我不理解这是为什么?因为你已经使用了 for i in range(len(s)/2)],为什么还是两两自由组合?您能帮我再看看吗?
真不好意思,给您添了这么多麻烦,多谢了!
下面是您生成的数据组:
Xiaoyu female 20 [('english', '80'), ('80', 'maths'), ('maths', '88')] [('song',
'44'), ('yang', '45')] Beijing
xiaoming male 20 [('english', '82'), ('82', 'maths')] [('huang', '44'), ('li', '45')]
Beijing
dawei male 21 [('english', '85'), ('85', 'maths'), ('maths', '94')] [('he', '46'),
('zhang', '48')] shanghai
xiaoxiao male 20 [('geography', '87')] [('lv', '44'), ('wang', '45')] Beijing
xiaohong female 21 [('english', '88'), ('88', 'maths'), ('maths', '84'), ('84',
'chinese'), ('chinese', '94')] [('hu', '46'), ('han', '48')] shanghai
feifei male 21 [] [('hu', '46'), ('han', '48')] shanghai
xiaoying female 20 [('english', '80'), ('80', 'maths'), ('maths', '86')] [('li',
'48')] shanghai


zhyeye
(stranger)
05-07-26 19:32
Re: 辛苦您了,limodou大哥!

那个冗余数据的问题解决了,
我把
if score:
s = score.split()
score = [(s[i], s[i+1]) for i in range(len(s)/2)]
改为
if score:
s = score.split()
score = [(s[i*2], s[i*2+1]) for i in range(len(s)/2)]
就可以了,我估计是您笔误,少敲了*2,现在好了!
多谢了,limodou大哥!

limodou版主
(Pooh-Bah)
05-07-26 22:12
Re: limodou大哥,程序有点问题

的确是如你所说应该是i*2的。

zhyeye
(stranger)
05-07-27 00:23
limodou大哥,再次请求帮助!

limodou大哥,我还是弄不好,你帮我看看,下面试我
合并后的程序,和出现的错误提示;
程序;


import sys, string

header = """<?xml version = "1.0"?>

<?xml:stylesheet type = "text/xsl"

href = "xszt.xsl"?>

<xueshengzhuangtai>"""



body="""<number1>

<name>%(name)s</name>

<gender>%(sex)s</gender>

<age>%(age)s</age>

<result_exam>

<course>%(course)s</course>

<score>%(score)s</score>

</result_exam>

<family>

<parent>%(parent)s</parent>

<age>%(parent_age)s</age>

</family>

<city>%(city)s</city>

</number1>"""



footer="""</xueshengzhuangtai>"""



def deal_body():



for line in file('/yejy/bioinf/d.txt'):

v = [x.strip() for x in line.rstrip().split('*')][:-1]

name, sex, age, result_exam, family, city = tuple(v)

if result_exam:

r = result_exam.split()

result_exam = [(r[i*2], r[i*2+1]) for i in range(len(r)/2)]

course = r[i*2]

score = r[i*2+1]

else:

result_exam = []

if family:

f = family.split()

family = [(f[i*2], f[i*2+1]) for i in range(len(f)/2)]

parent = f[i*2]

parent_age = f[i*2+1]

else:

family = []

print body % locals()



if __name__ == '__main__':

print header

deal_body()

print footer


错误提示;
Traceback (most recent call last):
File "C:/Program Files/python/test10.py", line 47, in ?
print body % locals()
KeyError: 'name'
我已经引入模块了,所以我不知道该是什么样子?
麻烦您了!

passworld
(enthusiast)
05-07-27 01:09
Re: limodou大哥,再次请求帮助!

你的 print body 在什么地方?应该在 for 里面。



limodou版主
(Pooh-Bah)
05-07-27 09:01
Re: limodou大哥,再次请求帮助!

如passworld所说缩近不对,应该与for同级。

zhyeye
(stranger)
05-07-27 16:20
回passworld和limodou大哥,都有点问题

我把二位的建议和输出的结果贴上来,你们再帮忙看看,多谢了!
首先是limodou大哥print body与 for同级的结果:
<?xml version = "1.0"?>
<?xml:stylesheet type = "text/xsl"
href = "xszt.xsl"?>
<xueshengzhuangtai>
<number1>
<name>xiaoying</name>
<gender>female</gender>
<age>20</age>
<result_exam>
<course>geography</course>
<score>90</score>
</result_exam>
<family>
<parent>han</parent>
<age>48</age>
</family>
<city>shanghai</city>
</number1>
</xueshengzhuangtai>
接着是passworld的在for里面:
<?xml version = "1.0"?>
<?xml:stylesheet type = "text/xsl"
href = "xszt.xsl"?>
<xueshengzhuangtai>
<number1>
<name>Xiaoyu</name>
<gender>female</gender>
<age>20</age>
<result_exam>
<course>chinese</course>
<score>92</score>
</result_exam>
<family>
<parent>yang</parent>
<age>45</age>
</family>
<city>Beijing</city>
</number1>
<number1>
<name>xiaoming</name>
<gender>male</gender>
<age>20</age>
<result_exam>
<course>maths</course>
<score>84</score>
</result_exam>
<family>
<parent>li</parent>
<age>45</age>
</family>
<city>Beijing</city>
</number1>
<number1>
<name>dawei</name>
<gender>male</gender>
<age>21</age>
<result_exam>
<course>chinese</course>
<score>89</score>
</result_exam>
<family>
<parent>zhang</parent>
<age>48</age>
</family>
<city>shanghai</city>
</number1>
<number1>
<name>xiaoxiao</name>
<gender>male</gender>
<age>20</age>
<result_exam>
<course>geography</course>
<score>87</score>
</result_exam>
<family>
<parent>wang</parent>
<age>45</age>
</family>
<city>Beijing</city>
</number1>
<number1>
<name>xiaohong</name>
<gender>female</gender>
<age>21</age>
<result_exam>
<course>history</course>
<score>78</score>
</result_exam>
<family>
<parent>han</parent>
<age>48</age>
</family>
<city>shanghai</city>
</number1>
<number1>
<name>feifei</name>
<gender>male</gender>
<age>21</age>
<result_exam>
<course>history</course>
<score>78</score>
</result_exam>
<family>
<parent>han</parent>
<age>48</age>
</family>
<city>shanghai</city>
</number1>
<number1>
<name>xiaoying</name>
<gender>female</gender>
<age>20</age>
<result_exam>
<course>geography</course>
<score>90</score>
</result_exam>
<family>
<parent>han</parent>
<age>48</age>
</family>
<city>shanghai</city>
</number1>
</xueshengzhuangtai>
与for同级时只输出了最后一条记录,而在for里面时则输出了所有记录,所以,我想应该是在for里面,但是,还有一个问题,就是为什么所有的
<result_exam>
<course>geography</course>
<score>90</score>
</result_exam>
<family>
<parent>han</parent>
<age>48</age>
</family>
都只是显示一组数据,是不是我的body有问题?
请帮忙看看!多谢,多谢!

passworld
(enthusiast)
05-07-27 16:51
Re: 回passworld和limodou大哥,都有点问题

你这也太死读书了吧?你需要一个循环或者函数专门处理分数:


def deal_result(result):

ret = []

for i in result:

ret.append('''/

<course>%s</course>

<score>%s</score>''' % (i[0], i[1]))

return '/n'.join(ret)






zhyeye
(stranger)
05-07-27 17:55
Re: 回passworld和limodou大哥,都有点问题

弱弱的问:我应该把它放在什么位置呢?我尝试了放在print body之前和之后,还有放在else之后都不起作用,出现错误,您能告诉我这是怎么回事吗?
多谢了!
下面试我加了之后的程序(#后是第一次放的位置);
import sys, string
header = """<?xml version = "1.0"?>
<?xml:stylesheet type = "text/xsl"
href = "xszt.xsl"?>
<xueshengzhuangtai>"""

body="""<number1>
<name>%(name)s</name>
<gender>%(sex)s</gender>
<age>%(age)s</age>
<result_exam>
<course>%(course)s</course>
<score>%(score)s</score>
</result_exam>
<family>
<parent>%(parent)s</parent>
<age>%(parent_age)s</age>
</family>
<city>%(city)s</city>
</number1>"""

footer="""</xueshengzhuangtai>"""

def deal_body():

for line in file('/yejy/bioinf/d.txt'):
v = [x.strip() for x in line.rstrip().split('*')][:-1]
name, sex, age, result_exam, family, city = tuple(v)
if result_exam:
r = result_exam.split()
result_exam = [(r[i*2], r[i*2+1]) for i in range(len(r)/2)]
course = r[i*2]
score = r[i*2+1]
else:
result_exam = []
course = ''
score = ''

if family:
f = family.split()
family = [(f[i*2], f[i*2+1]) for i in range(len(f)/2)]
parent = f[i*2]
parent_age = f[i*2+1]
else:
family = []
parent = ''
parent_age = ''

def deal_result_exam(result_exam):
result_exam = []
for i in result_exam:
result_exam.append('''/
<course>%s</course>
<score>%s</score>''' % (i[0], i[1]))
return '/n'.join(result_exam)
def deal_family(family):
family= []
for i in family:
family.append('''/
<parent>%s</parent>
<age>%s</age>''' % (i[0], i[1]))
return '/n'.join(family)

print body % locals()
#def deal_result_exam(result_exam):
#result_exam = []
#for i in result_exam:
#result_exam.append('''/
#<course>%s</course>
#<score>%s</score>''' % (i[0], i[1]))
#return '/n'.join(result_exam)
#def deal_family(family):
#family = []
#for i in family:
#family.append('''/
#<parent>%s</parent>
#<age>%s</age>''' % (i[0], i[1]))
# return '/n'.join(family)

if __name__ == '__main__':
print header
deal_result_exam(result_exam)
deal_family(family)
deal_body()
print footer
错误显示:
Traceback (most recent call last):
File "C:/Program Files/python/test10.py", line 82, in ?
deal_result_exam(result_exam)
NameError: name 'result_exam' is not defined

passworld
(enthusiast)
05-07-27 19:47
Re: 回passworld和limodou大哥,都有点问题

看来你真是一点python都不会,做完这个项目后好好学学python吧,很有用的一个语言:


#!/usr/bin/python

import sys, string

header = """&lt;?xml version = "1.0"?&gt;

&lt;?xml:stylesheet type = "text/xsl"

href = "xszt.xsl"?&gt;

&lt;xueshengzhuangtai&gt;"""



body="""&lt;number1&gt;

&lt;name&gt;%(name)s&lt;/name&gt;

&lt;gender&gt;%(sex)s&lt;/gender&gt;

&lt;age&gt;%(age)s&lt;/age&gt;

&lt;result_exam&gt;

%(results)s

&lt;/result_exam&gt;

&lt;family&gt;

%(parents)s

&lt;/family&gt;

&lt;city&gt;%(city)s&lt;/city&gt;

&lt;/number1&gt;"""



footer="""&lt;/xueshengzhuangtai&gt;"""

FNAME='/yejy/bioinf/d.txt'

def deal_body(fname):



try:

for line in file(fname):

v = [x.strip() for x in line.rstrip().split('*')][:-1]

name, sex, age, result_exam, family, city = tuple(v)

if result_exam:

r = result_exam.split()

result_exam = [(r[i*2], r[i*2+1]) for i in range(len(r)/2)]

else:

result_exam = []

if family:

f = family.split()

family = [(f[i*2], f[i*2+1]) for i in range(len(f)/2)]

else:

family = []



results = deal_result_exam(result_exam)

parents = deal_family(family)



print body % locals()

except:

print 'Error:', line

print sys.exc_info()[1]

sys.exit()



def deal_result_exam(results):

result_exam = []

for i in results:

result_exam.append('''/

&lt;course&gt;%s&lt;/course&gt;

&lt;score&gt;%s&lt;/score&gt;''' % (i[0], i[1]))

return '/n'.join(result_exam)



def deal_family(family):

result_family= []

for i in family:

result_family.append('''/

&lt;parent&gt;%s&lt;/parent&gt;

&lt;age&gt;%s&lt;/age&gt;''' % (i[0], i[1]))

return '/n'.join(result_family)



if __name__ == '__main__':

print header

if len(sys.argv) == 2:

fname = sys.argv[1]

else:

fname = FNAME

deal_body(fname)

print footer






passworld
(enthusiast)
05-07-27 19:48
附加档案
Re: 回passworld和limodou大哥,都有点问题

附件源码

zhyeye
(stranger)
05-07-27 21:04
太感谢您了!

我的确什么都不懂,才刚刚开始学,但是老板非要让我完成这个任务,所以才给您和limodou大哥添了这么多麻烦,真的太感谢你们了。python真的很有意思,我一定会好好学习的。
多谢你们了!

limodou版主
(Pooh-Bah)
05-07-27 23:09
Re: 太感谢您了!

努力学吧。其实你的问题如果转换成模板工作会非常简单,当然思路就复杂一些,而且还要用到其它的包。但是使用模板的好处是:模板用于处理显示,你的任务就 是分析出附合模板的数据结构,然后与模板相结合。这样你的主要关注点就是如何解析原始数据,然后如何生成附合模板要求的数据结构。

alula
(addict)
05-07-28 12:00
关于模板

http://www.donews.net/limodou/archive/2004/11/10/166282.aspx
在上面的链接,我看了您介绍Meteor的文章。目前模板比较有兴趣。
如果用Meteor干这个活儿,写出来的代码大概是什么个模样呢?

我修改了自己的模板分析程序,干这个活儿,代码是这个样子的:


#! /usr/bin/python



import re, string, sys

from StringIO import StringIO



keywords = 'end', 'template', 'if', 'elif', 'else', 'apply-template', 'include'



_varname = re.compile('/${(/w+)}')

_meta = re.compile('^/s*<!--/s*#/s*(%s)(.*)-->/s*




alula
(addict)
05-07-28 12:10
Re: 关于模板

应用的时候,应该是这样:

编写模板文件:
templatefile.txt:


<?xml version = "1.0"?>

<?xml:stylesheet type = "text/xsl" href = "xszt.xsl"?>

<!-- #template 'glob': -->

<number1>

<name>${name}</name>

<gender>${sex}</gender>

<age>${age}</age>

<result_exam>

<!-- #template 'result_exam': -->

<subject>${subject}</subject>

<score>${score}</score>

<!-- #end -->

<!-- #apply-template 'result_exam' -->

</result_exam>

<family>

<!-- #template 'family': -->

<name>${name}</name>

<age>${age}</age>

<!-- #end -->

<!-- #apply-template 'family' -->

</family>

<city>${city}</city>

</number1>

<!-- #end -->

<xueshengzhuangtai>

<!-- #apply-template 'glob' -->

</xueshengzhuangtai>


从数据文件分析出数据:
Xiaoyu * female * 20 * english 80 maths 88 chinese 92 * song 44 yang 45 * Beijing *
wu * male * 20 * c/c++ 8 maths 8 listening 9 * wu 4 wu 4 * ShenZhen *

分析出的数据结构:
print data
[{'city': 'Beijing', 'result_exam': [{'score': '92', 'subject': 'chinese'}, {'sc
ore': '88', 'subject': 'maths'}, {'score': '80', 'subject': 'english'}], 'name':
'Xiaoyu', 'family': [{'age': '45', 'name': 'yang'}, {'age': '44', 'name': 'song'}], 'age': '20', 'sex': 'female'}, {'city': 'ShenZhen', 'result_exam': [{'score' : '9', 'subject': 'listening'}, {'score': '8', 'subject': 'maths'}, {'score': '8', 'subject': 'c/c++'}], 'name': 'wu', 'family': [{'age': '4', 'name': 'wu'}, {'age': '4', 'name': 'wu'}], 'age': '20', 'sex': 'male'}]

然后是调用:
thtml.printf('templatefile.txt', data)
输出:


<?xml version = "1.0"?>

<?xml:stylesheet type = "text/xsl" href = "xszt.xsl"?>





<xueshengzhuangtai>

<number1>

<name>Xiaoyu</name>

<gender>female</gender>

<age>20</age>

<result_exam>

<subject>chinese</subject>

<score>92</score>

<subject>maths</subject>

<score>88</score>

<subject>english</subject>

<score>80</score>

</result_exam>

<family>

<name>yang</name>

<age>45</age>

<name>song</name>

<age>44</age>

</family>

<city>Beijing</city>

</number1>

<number1>

<name>wu</name>

<gender>male</gender>

<age>20</age>

<result_exam>

<subject>listening</subject>

<score>9</score>

<subject>maths</subject>

<score>8</score>

<subject>c/c++</subject>

<score>8</score>

</result_exam>

<family>

<name>wu</name>

<age>4</age>

<name>wu</name>

<age>4</age>

</family>

<city>ShenZhen</city>

</number1>

</xueshengzhuangtai>





limodou版主
(Pooh-Bah)
05-07-28 14:27
Re: 关于模板

我看了一下你的模板程序感觉与meteor很象,基本上都是
以数据驱动的,即如果数据是list,那么就循环。不过meteor
是纯以数据驱动,没有if else之类的处理。而且它的模板
也不是单一定义的,而是采用python程序的方式进行定义
的。因此meteor更象一个程序,不是简单的模板。写出来
的程序如下:

------------------ t.py 模板程序 -------------------------

from meteor import *

xml = T("""<?xml version = "1.0"?>
<?xml:stylesheet type = "text/xsl" href = "xszt.xsl"?>
<xueshengzhuangtai>
${number1}</xueshengzhuangtai>
""")

number1 = T("""<number1>
<name>${name}</name>
<gender>${sex}</gender>
<age>${age}</age>
<result_exam>
${result_exam} </result_exam>
<family>
${family} </family>
<city>${city}</city>
</number1>
""")

result_exam = T(""" <subject>${subject}</subject>
<score>${score}</score>
""")

family = T(""" <name>${name}</name>
<age>${age}</age>
""")

----------------------------- b.py 处理程序 ----------------------
from meteor import *

vars = {'number1':[
{'city': 'Beijing',
'result_exam': [
{'score': '92', 'subject': 'chinese'},
{'score': '88', 'subject': 'maths'},
{'score': '80', 'subject': 'english'}
],
'name':'Xiaoyu',
'family': [
{'age': '45', 'name': 'yang'},
{'age': '44', 'name': 'song'}
],
'age': '20',
'sex': 'female'},
{'city': 'ShenZhen',
'result_exam': [
{'score' : '9','subject': 'listening'},
{'score': '8', 'subject': 'maths'},
{'score': '8', 'subject':'c/c++'}],
'name': 'wu',
'family': [
{'age': '4', 'name': 'wu'},
{'age': '4', 'name': 'wu'}],
'age': '20',
'sex': 'male'}
]
}

if __name__ == '__main__':
template = Template()
template.load('t.py', 'python', "/$/{", "/}")
print template.value('xml', vars)

这里数据的表示与你的基本上是一样的,不同在于meteor
的数据一上来就是一个字典,而你的是一个list。meteor的
模板变量可以自由定义。它缺省是<#var#>这种定义,为了
符合你的模板变量的定义改为:
template.load('t.py', 'python', "/$/{", "/}")

alula
(addict)
05-07-29 09:48
Re: 关于模板

谢谢您的热心回答。
我浏览了一下meteor的代码,给人感觉是想做出一个灵活的框架,所以代码也复杂了一些。
这个THtml代码就少一些,没有什么灵活的可配置参数,但是挺实用。在效率上也特别照顾了。


limodou版主
(Pooh-Bah)
05-07-29 10:41
Re: 关于模板

是的。meteor本身可以自定义模板标记,通过python对象的方式来解决子模板的定义问题(你的模板需要一个明确的模板定义),这样可以方便组合模 板对象。因为它是一个程序,因此你也可以方便进行修改。同时也提供在复杂情况下生成自已的模板处理程序,但可以沿用现有的框架。同时meteor包还提供 了方便生成dict结构的Tree类,可以以一种路径的方式来生成一个 dict。再有就是提供了一个简单的TemplateScript 类,支持一些文件和目录的操作,这样文件模板与目录处理相结合,功能就比较完整。不过目前也是个人使用。

Contact Us LINUXFORUM.NET

% '|'.join(keywords))



def _G_repl(txt, dct):

return re.sub(_varname, lambda g: str(dct.get(g.group(1))), txt)



def _G_meta(line):

if line.lstrip()[:4] == '<!--':

res = re.search(_meta, line)

if res:

return res.group(1, 2)

return 0, 0



class THtml:

def __init__(self, src):

self._src = src

def begin(self, dct):

line = self._src.readline()

while line:

if self.recv(line, dct) == 0:

break

line = self._src.readline()

def recv(self, line, dct):

key, exp = _G_meta(line)

if key:

return self.statement(key, exp, dct)

return self.normal(line, dct)

def statement(self, key, exp, dct):

assert key in ('if', 'template', 'apply-template', 'include')

if key == 'if':

exp = eval(_G_repl(exp[:exp.rindex(':')], dct))

If(self._src, exp).begin(dct)

elif key == 'template':

exp = eval(_G_repl(exp[:exp.rindex(':')], dct))

txt = []

Extract(self._src, txt).begin(dct)

txt.pop()

_templates[exp] = StringIO(''.join(txt))

elif key == 'include':

exp = eval(_G_repl(exp, dct))

xf = file(exp)

THtml(xf).begin(dct)

elif key == 'apply-template':

exp = eval(_G_repl(exp, dct))

vf = _templates[exp]

for d in dct[exp]:

THtml(vf).begin(d)

vf.seek(0)

return 1

def normal(self, line, dct):

sys.stdout.write(_G_repl(line, dct))

return 1



class Skip(THtml):

def __init__(self, src):

THtml.__init__(self, src)

def statement(self, key, exp, dct):

if key == 'end':

return 0

elif key in ('if', 'template'):

Skip(self._src).begin(dct)

return 1

def normal(self, line, dct):

return 1



class Extract(THtml):

def __init__(self, src, lines):

THtml.__init__(self, src)

self._lines = lines

def recv(self, line, dct):

self._lines.append(line)

return THtml.recv(self, line, dct)

def statement(self, key, exp, dct):

if key == 'end':

return 0

elif key in ('if', 'template'):

Extract(self._src, self._lines).begin(dct)

return 1

def normal(self, line, dct):

return 1



class If(THtml):

def __init__(self, src, bool):

THtml.__init__(self, src)

self._true = bool

def statement(self, key, exp, dct):

if key == 'end':

return 0

elif key in ('elif', 'else'):

if self._true:

Skip(self._src).begin(dct)

else:

if key == 'elif':

self._true = eval(_G_repl((exp[: exp.rindex(':')]), dct))

else:

self._true = 1

else:

if self._true:

return THtml.statement(self, key, exp, dct)

elif key in ('if', 'template'):

Skip(self._src).begin(dct)

return 1

def normal(self, line, dct):

if self._true:

THtml.normal(self, line, dct)

return 1



_dicts = {}

_templates = {}



from StringIO import StringIO



def printf(vf, glob):

if type(vf) == str:

THtml(file(vf)).begin(glob)

else:

THtml(vf).begin(glob)



def test():

content = """<?xml version = "1.0"?>

<?xml:stylesheet type = "text/xsl" href = "xszt.xsl"?>



<!-- #template 'glob': -->

<number1>

<name>${name}</name>

<gender>${sex}</gender>

<age>${age}</age>

<result_exam>

<!-- #template 'result_exam': -->

<subject>${subject}</subject>

<score>${score}</score>

<!-- #end -->

<!-- #apply-template 'result_exam' -->

</result_exam>

<family>

<!-- #template 'family': -->

<name>${name}</name>

<age>${age}</age>

<!-- #end -->

<!-- #apply-template 'family' -->

</family>

<city>${city}</city>

</number1>

<!-- #end -->



<xueshengzhuangtai>

<!-- #apply-template 'glob' -->

</xueshengzhuangtai>

"""



glob = test_data()

printf(StringIO(content), { 'glob' : glob })



def test_data():

data = """Xiaoyu * female * 20 * english 80 maths 88 chinese 92 * song 44 yang 45 * Beijing *

wu * male * 20 * c/c++ 8 maths 8 listening 9 * wu 4 wu 4 * ShenZhen * """

glob = []

for line in data.splitlines():

h = {}

v = [x.strip() for x in line.rstrip().split('*')][:-1]

h['name'], h['sex'], h['age'], result_exam, family, h['city'] = v

h['result_exam'] = []

h['family'] = []

if result_exam:

r = result_exam.split()

while r:

t = {}

t['score'], t['subject'] = r.pop(), r.pop()

h['result_exam'].append(t)

if family:

r = family.split()

while r:

t = {}

t['age'], t['name'] = r.pop(), r.pop()

h['family'].append(t)

glob.append(h)

return glob



if __name__ == '__main__':

test()







alula
(addict)
05-07-28 12:10
Re: 关于模板

应用的时候,应该是这样:

编写模板文件:
templatefile.txt:

___FCKpd___8

从数据文件分析出数据:
Xiaoyu * female * 20 * english 80 maths 88 chinese 92 * song 44 yang 45 * Beijing *
wu * male * 20 * c/c++ 8 maths 8 listening 9 * wu 4 wu 4 * ShenZhen *

分析出的数据结构:
print data
[{'city': 'Beijing', 'result_exam': [{'score': '92', 'subject': 'chinese'}, {'sc
ore': '88', 'subject': 'maths'}, {'score': '80', 'subject': 'english'}], 'name':
'Xiaoyu', 'family': [{'age': '45', 'name': 'yang'}, {'age': '44', 'name': 'song'}], 'age': '20', 'sex': 'female'}, {'city': 'ShenZhen', 'result_exam': [{'score' : '9', 'subject': 'listening'}, {'score': '8', 'subject': 'maths'}, {'score': '8', 'subject': 'c/c++'}], 'name': 'wu', 'family': [{'age': '4', 'name': 'wu'}, {'age': '4', 'name': 'wu'}], 'age': '20', 'sex': 'male'}]

然后是调用:
thtml.printf('templatefile.txt', data)
输出:

___FCKpd___9


limodou 版主
(Pooh-Bah)
05-07-28 14:27
Re: 关于模板

我看了一下你的模板程序感觉与meteor很象,基本上都是
以数据驱动的,即如果数据是list,那么就循环。不过meteor
是纯以数据驱动,没有if else之类的处理。而且它的模板
也不是单一定义的,而是采用python程序的方式进行定义
的。因此meteor更象一个程序,不是简单的模板。写出来
的程序如下:

------------------ t.py 模板程序 -------------------------

from meteor import *

xml = T("""<?xml version = "1.0"?>
<?xml:stylesheet type = "text/xsl" href = "xszt.xsl"?>
<xueshengzhuangtai>
${number1}</xueshengzhuangtai>
""")

number1 = T("""<number1>
<name>${name}</name>
<gender>${sex}</gender>
<age>${age}</age>
<result_exam>
${result_exam} </result_exam>
<family>
${family} </family>
<city>${city}</city>
</number1>
""")

result_exam = T(""" <subject>${subject}</subject>
<score>${score}</score>
""")

family = T(""" <name>${name}</name>
<age>${age}</age>
""")

----------------------------- b.py 处理程序 ----------------------
from meteor import *

vars = {'number1':[
{'city': 'Beijing',
'result_exam': [
{'score': '92', 'subject': 'chinese'},
{'score': '88', 'subject': 'maths'},
{'score': '80', 'subject': 'english'}
],
'name':'Xiaoyu',
'family': [
{'age': '45', 'name': 'yang'},
{'age': '44', 'name': 'song'}
],
'age': '20',
'sex': 'female'},
{'city': 'ShenZhen',
'result_exam': [
{'score' : '9','subject': 'listening'},
{'score': '8', 'subject': 'maths'},
{'score': '8', 'subject':'c/c++'}],
'name': 'wu',
'family': [
{'age': '4', 'name': 'wu'},
{'age': '4', 'name': 'wu'}],
'age': '20',
'sex': 'male'}
]
}

if __name__ == '__main__':
template = Template()
template.load('t.py', 'python', "/$/{", "/}")
print template.value('xml', vars)

这里数据的表示与你的基本上是一样的,不同在于meteor
的数据一上来就是一个字典,而你的是一个list。meteor的
模板变量可以自由定义。它缺省是<#var#>这种定义,为了
符合你的模板变量的定义改为:
template.load('t.py', 'python', "/$/{", "/}")

alula
(addict)
05-07-29 09:48
Re: 关于模板

谢谢您的热心回答。
我浏览了一下meteor的代码,给人感觉是想做出一个灵活的框架,所以代码也复杂了一些。
这个THtml代码就少一些,没有什么灵活的可配置参数,但是挺实用。在效率上也特别照顾了。


limodou 版主
(Pooh-Bah)
05-07-29 10:41
Re: 关于模板

是的。meteor本身可以自定义模板标记,通过python对象的方式来解决子模板的定义问题(你的模板需要一个明确的模板定义),这样可以方便组合模 板对象。因为它是一个程序,因此你也可以方便进行修改。同时也提供在复杂情况下生成自已的模板处理程序,但可以沿用现有的框架。同时meteor包还提供 了方便生成dict结构的Tree类,可以以一种路径的方式来生成一个 dict。再有就是提供了一个简单的TemplateScript 类,支持一些文件和目录的操作,这样文件模板与目录处理相结合,功能就比较完整。不过目前也是个人使用。

Contact Us LINUXFORUM.NET

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值