由XML Literal引发的思考
2010-04-24 00:21 FantasySoft 阅读(2294) 评论(3) 编辑 收藏 举报一年多没在首页露脸了,昨天凌晨写就了一篇有关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下运行正常。