一年多没在首页露脸了,昨天凌晨写就了一篇有关IronPython的随笔,发布的时候我确实有点诚惶诚恐。不过还好,至少引得几位朋友的围观,还能碰上老朋友木野狐,我心足矣!木野狐在评论中给我留下了一个非常棒的问题:“IronPython能否模拟或者接近vb.net的xml literal那样的语法?”尽管我对IronPython处理XML的能力自信满满,但是,面对XML Literal这样的词汇,我有点踌躇了。于是,我开始了一系列的研究。
首先,什么是XML Literal呢?原来,这是在VB.NET 9.0才引入的一个用于构建XML对象的新特性,并且只有VB.NET 9.0才支持。我们都知道,要创建XML树,可以使用Linq中的API,如下所示(代码出自VB.NET 9.0: XML Literal):
New XElement( " Process " , _
New XAttribute( " ThreadCount " , " 2 " ), " Some Process " ))
对于上述的代码,我们可以使用更简单的方式进行赋值,那就是直接将XML树写出来:
< Process ThreadCount = " 2 " > Some Name </ Process >
</ Processes >
这就是VB.NET特有的XML Literal了。这个特性不仅仅简化了XElement构建的过程,更重要的是,我们可以在构建的过程中添加某些查询!譬如下面的代码(代码出自XML Literals Overview):
< contact >
< name > Patrick Hines </ name >
< % = From p In phoneNumbers2
Select < phone type =< % = p.Type % >>< % = p.Number % ></ phone >
% >
</ contact >
看到这些例子,我着实被震撼了。VB.NET对XML的支持力度可谓空前绝后了,甚至一些忠实的C#拥趸都因此拜倒在VB.NET的石榴裙下。C#社区也纷纷要求为C#增加XML Literal特性,更有甚者竭力找到了Anders为大家留下的后门。对于XML Literal有兴趣的朋友,可以阅读以下几篇来自MSDN的文章:XML Literals Overview和Embedded Expressions in XML。
对于XML的处理,VB.NET有此锐器,那么IronPython是否有相似的工具呢?Michael搜肠刮肚、翻箱倒柜才找到本属于Python的minidom模块,其中的parseString方法拥有稍微接近的处理能力,但可惜的是,parseString方法返回的对象只能是Document对象,而非ELement,这也意味着parseString并不拥有XML Literal的魔力。
>>> xmlElement = parseString( """
... <Processes>
... <Process ThreadCount="2">Some Name</Process>
... </Processes>
... """ )
上述代码在IronPython 2.6中执行,会出现错误。这是因为IronPython对minidom的移植还没有全部完成,缺失了某些模块。具体的workaround如下:
1、下载FePy并且解压至某个目录,譬如D:\FePy;
2、将D:\FePy\Lib\pyexpat.py、 D:\FePy\Lib\xml\dom\expatbuilder.py、D:\FePy\Lib\xml\parsers\expat.py赋值到IronPython相对应的目录中。如第一个文件就复制到D:\IronPython 2.6\Lib的目录下;
3、搜索expatbuilder.py中的NewStyle变量,并且将其删除。
[后记:]一位在Youtube工作的牛人Fredrik Lundh早在2002年就提出了为Python添加XML Literal的功能,
但是直到现在还没有出现类似的功能,至少Michael现在还没有找到
。有发现的朋友请告知一声,衷心感谢!
经过limodou兄的指点,Michael找到了xml.etree.ElementTree模块,其中的xml.etree.ElementTree.XML(text)方法在一定程度实现XML Literal特性,毕竟它返回的是Element对象,那么我们就可以基于此进行操作了。xml.etree.ElementTree模块在IronPython 2.6下运行正常。