今天使用PowerShell来操作XML遇到两个问题,之前一直用的C#操作XML,所以我想在PowerShell上应该跟C#一样的。

先准备好XML文件如下,我给它命名test.xml

 

 
  
  1. <?xml version="1.0" encoding="utf-8" ?>   
  2. <root>   
  3.   <users job="salas">   
  4.     <user>   
  5.       <name>Joe</name>   
  6.       <age>17</age>   
  7.     </user>   
  8.     <user>   
  9.       <name>Kate</name>   
  10.       <age>12</age>   
  11.     </user>   
  12.   </users>   
  13.   <users job="developer">   
  14.     <user>   
  15.       <name>David</name>   
  16.       <age>23</age>   
  17.     </user>   
  18.     <user>   
  19.       <name>Eath</name>   
  20.       <age>54</age>   
  21.     </user>   
  22.   </users>   
  23. </root>   

然后下面是一段简单的C#的代码,来获取上述XML文件中的节点

 

 
  
  1. static void Main(string[] args)   
  2.         {   
  3.             XmlDocument doc = new XmlDocument();   
  4.             doc.Load("test.xml");  
  5.  
  6.             XmlElement root = doc.DocumentElement;   
  7.             XmlNodeList users = root.SelectNodes("users");  
  8.  
  9.             Console.WriteLine(users[0].OuterXml);   
  10.             Console.WriteLine(users[0].Attributes["job"].Value);   
  11.         }  
  12.  

工作一切正常,现在将它改写成PowerShell来操作,代码如下:

 

 
  
  1. $doc=new-object System.xml.XmlDocument   
  2. $doc.load("test.xml")   
  3. $root=$doc.DocumentElement   
  4. $users=$root.SelectNodes("users")  
  5.  
  6. write-host $users[0].outerxml   
  7. write-host $users[0].Attributes["job"].value  

 

两个都是用的.net 2.0框架。

PS脚本就在运行的时候出错了,错误原因是

Unable to index into an object of type System.Xml.XPathNodeList

为什么在C#里可以使用索引,在PS里面就不行哩?

在网上苦寻半天,勉强算是找到一个答案

http://connect.microsoft.com/PowerShell/feedback/details/339557/ctp-unable-to-index-into-an-object-of-type-system-management-managementobjectcollection

This is by design.
ManagementObjectCollection class does not have an indexer.

同理也就是说类XPathNodeList没有实现索引器,那为什么C#里又可以?

XPathNodeList类是个内部类,MSDN上可没有解释,只能通过Reflector来查看。

这个网址也能查看:

http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Xml&type=XPathNodeList

可以知道它继承自XmlNodeList,查看XmlNodeList可以知道它实现了索引器方法,所以在C#里就可以调用了。

那PowerShell不能调用的原因就是它只能查找到本类的实现方法或者属性,无法去调用父类的方法或者属性咯!?

修改PowerShell脚本如下,通过item()方法来获取。

 

 
  
  1. $doc=new-object System.xml.XmlDocument   
  2. $doc.load("D:\workspace\TestFolder\ConsoleApplication\PowershellXMLTest\test.xml")   
  3. $root=$doc.DocumentElement   
  4. $users=$root.SelectNodes("users")  
  5.  
  6. write-host $users.item(0).outerxml   
  7. write-host $users.item(0).Attributes["job"].value 

 

好吧!问题又来了,这次是

Unable to index into an object of type System.Xml.XmlAttributeCollection

查看源代码,发现它实现了索引方法的啊?什么原因?

难道是PS不支持C#中实现的索引方法?

又再次修改脚本如下,终于解决问题,但是问题仍在。特此记录一下。

 

 
  
  1. $doc=new-object System.xml.XmlDocument   
  2. $doc.load("D:\workspace\TestFolder\ConsoleApplication\PowershellXMLTest\test.xml")   
  3. $root=$doc.DocumentElement   
  4. $users=$root.SelectNodes("users")  
  5.  
  6. write-host $users.item(0).outerxml   
  7. write-host $users.item(0).GetAttribute("job")