PowerShell处理XML系列文章
PowerShell扩展类型系统(ETS)确保了对象可以被转换成有意义的文本。此外,它还可以传递额外的属性和方法给对象。这些操作的精确定义被存放在扩展名为.ps1xml的文件中。
扩展类型系统的XML数据
不论何时,PowerShell要将对象转换成文本,都会搜索它自己的内置纪录中关于对象的描述和转换。正确的文件包含了XML:它的文件名以.format.ps1xml收尾,这些文件位于PowerShell的根目录$pshome下。
PS> Dir $pshome\*.format.ps1xml Directory: C:\Windows\System32\WindowsPowerShell\v1.0 Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2013/6/18 22:50 27338 Certificate.format.ps1xml -a--- 2013/6/18 22:50 27106 Diagnostics.Format.ps1xml -a--- 2013/6/18 22:50 147702 DotNetTypes.format.ps1xml -a--- 2013/6/18 22:50 14502 Event.Format.ps1xml -a--- 2013/6/18 22:50 21293 FileSystem.format.ps1xml -a--- 2013/6/18 22:50 287938 Help.format.ps1xml -a--- 2013/6/18 22:50 97880 HelpV3.format.ps1xml -a--- 2013/6/19 2:30 105230 PowerShellCore.format.ps1xml -a--- 2013/6/18 22:50 18612 PowerShellTrace.format.ps1xml -a--- 2013/6/18 22:50 13659 Registry.format.ps1xml -a--- 2013/6/18 22:50 17731 WSMan.Format.ps1xml
所有的这些文件包含了众多的视图,你可以使用PowerShell 支持的XML方法来检验它。
[xml]$file = Get-Content "$pshome\dotnettypes.format.ps1xml" $file.Configuration.ViewDefinitions.View
Name ViewSelectedBy ListControl ---- -------------- ----------- System.CodeDom.Compiler.CompilerError ViewSelectedBy ListControl System.Reflection.Assembly ViewSelectedBy System.Reflection.AssemblyName ViewSelectedBy System.Globalization.CultureInfo ViewSelectedBy System.Diagnostics.FileVersionInfo ViewSelectedBy System.Management.ManagementObject#root\cimv2\Win32_PingStatus ViewSelectedBy Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_PingStatus ViewSelectedBy System.Management.ManagementObject#root\default\SystemRestore ViewSelectedBy Microsoft.Management.Infrastructure.CimInstance#root/default/SystemRestore ViewSelectedBy Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_Product ViewSelectedBy System.Net.NetworkCredential ViewSelectedBy System.Management.Automation.PSMethod ViewSelectedBy Microsoft.Management.Infrastructure.CimInstance#__PartialCIMInstance ViewSelectedBy
查找预定义的视图
预定义的视图非常有意思,因为你可以在像format-table和format-list这样的格式化命令中使用-View参数来对指定的结果做出丰富的调整和更改。
Get-Process | Format-Table -view Priority Get-Process | Format-Table -view StartTime
很遗憾,没人告诉你像Priority 和 StartTime这样的视图或者其它视图已经存在。你可以查看相关的XML文件,视图文件显示每一个视图结点包含了子结点:Name,ViewSelectedBy,TableControl。但是开始,视图的原始XML数据可能看起来费解,不清楚。
使用一行命令即可重新格式化文本,让它方便阅读:
$xmldata.get_OuterXML().Replace("<", "`t<").Replace(">", ">`t").Replace(">`t`t<", ">`t<").Split("`t") | ForEach-Object {$x=0}{ If ($_.StartsWith("</")) {$x--} ` ElseIf($_.StartsWith("<")) { $x++}; (" " * ($x)) + $_; ` if ($_.StartsWith("</")) { $x--} elseif ` ($_.StartsWith("<")) {$x++} }
<View> <Name> System.CodeDom.Compiler.CompilerError </Name> <ViewSelectedBy> <TypeName> System.CodeDom.Compiler.CompilerError </TypeName> </ViewSelectedBy> <ListControl> <ListEntries> <ListEntry> <ListItems> <ListItem> <PropertyName> ErrorText </PropertyName> </ListItem> <ListItem> <PropertyName> Line </PropertyName> </ListItem> <ListItem> <PropertyName> Column </PropertyName> </ListItem> <ListItem> <PropertyName> ErrorNumber </PropertyName> </ListItem> <ListItem> <PropertyName> LineSource </PropertyName> </ListItem> </ListItems> </ListEntry> </ListEntries> </ListControl> </View>
每一个视图由一个Name,一个ViewSelectedBy中的.NET类型组成,作为视图合格的条件,TableControl结点也一样,指定对象被支持转换成文本。如果你想在一列中输出定义在XML文件中的所有的视图,Format-Table命令足矣,然后选择你想在摘要中显示的属性。
[xml]$file = Get-Content "$pshome\dotnettypes.format.ps1xml" $file.Configuration.ViewDefinitions.View | Format-Table Name, {$_.ViewSelectedBy.TypeName}
Name $_.ViewSelectedBy.TypeName ---- -------------------------- System.CodeDom.Compiler.CompilerError System.CodeDom.Compiler.CompilerError System.Reflection.Assembly System.Reflection.Assembly System.Reflection.AssemblyName System.Reflection.AssemblyName System.Globalization.CultureInfo System.Globalization.CultureInfo System.Diagnostics.FileVersionInfo System.Diagnostics.FileVersionInfo System.Diagnostics.EventLogEntry System.Diagnostics.EventLogEntry System.Diagnostics.EventLog System.Diagnostics.EventLog System.Version System.Version System.Drawing.Printing.PrintDocument System.Drawing.Printing.PrintDocument Dictionary System.Collections.DictionaryEntry ProcessModule System.Diagnostics.ProcessModule process System.Diagnostics.Process ProcessWithUserName System.Diagnostics.Process#IncludeUserName DirectoryEntry System.DirectoryServices.DirectoryEntry PSSnapInInfo System.Management.Automation.PSSnapInInfo PSSnapInInfo System.Management.Automation.PSSnapInInfo Priority System.Diagnostics.Process StartTime System.Diagnostics.Process service System.ServiceProcess.ServiceController System.Diagnostics.FileVersionInfo System.Diagnostics.FileVersionInfo System.Diagnostics.EventLogEntry System.Diagnostics.EventLogEntry System.Diagnostics.EventLog System.Diagnostics.EventLog System.TimeSpan System.TimeSpan System.TimeSpan System.TimeSpan System.TimeSpan System.TimeSpan System.AppDomain System.AppDomain System.ServiceProcess.ServiceController System.ServiceProcess.ServiceController System.Reflection.Assembly System.Reflection.Assembly System.Collections.DictionaryEntry System.Collections.DictionaryEntry process System.Diagnostics.Process DateTime System.DateTime System.Security.AccessControl.ObjectSecurity System.Security.AccessControl.ObjectSecurity System.Security.AccessControl.ObjectSecurity System.Security.AccessControl.ObjectSecurity System.Management.ManagementClass System.Management.ManagementClass Microsoft.Management.Infrastructure.CimClass Microsoft.Management.Infrastructure.CimClass System.Guid System.Guid System.Management.ManagementObject#root\cimv2\Win32_Ping... System.Management.ManagementObject#root\cimv2\Win32_Ping... ...............
你所看到是XML文件中定义的所有的视图了,第二列显示的就是视图定义的对象类型。其中的Priority和StartTime就是我们之前在上一个例子中使用的两个视图。看了第二列应当就会非常清楚,该视图是针对System.Diagnostics.Process对象,恰恰就是命令Get-Process获取的对象。
(Get-Process | Select-Object -first 1).GetType().FullName System.Diagnostics.Process
你可能会惊讶有些Name是成对出现的,例如System.TimeSpan。其原因正是上一个例子中提到的TableControl结点,一起的还有其它类型转换的结点ListControl, WideControl 和 CustomControl。这些结点在第一次概览时,不会被显示。原因是每一个视图只允许出现一个这样的结点。TableControl被输出时或多或少带有随机性,因为在转换第一条记录时,PowerShell是基于未知对象的转换。
接下来我们会提取出XML文件中所有的必须的信息。首先对视图按照ViewSelectedBy.TypeName排序,接着根据criterion(标准)来分组。你也可以按照只匹配出一次确定的对象类型来排序。你只需要那些值得在-view参数中指定的,存在多个对象类型的视图。
[xml]$file = Get-Content "$pshome\dotnettypes.format.ps1xml" $file.Configuration.ViewDefinitions.View | Sort-Object {$_.ViewSelectedBy.TypeName} | Group-Object {$_.ViewSelectedBy.TypeName} | Where-Object { $_.Count -gt 1} | ForEach-Object { $_.Group} | Format-Table Name, {$_.ViewSelectedBy.TypeName}, ` @{expression={if ($_.TableControl) { "Table" } elseif ` ($_.ListControl) { "List" } elseif ($_.WideControl) { "Wide" } ` elseif ($_.CustomControl) { "Custom" }};label="Type"} -wrap
如果对于这几行的格式化命令有任何疑问,可以参考第五章,主要讲格式化。关于像Format-Table与其它这样的格式化命令,其重要性在于可以让你在表格的列中显示特定的对象,属性,或者脚本块。如果你想在表格列中不直接显示属性,而是显示属性的子属性,那么子表达式是必须的。因为你对ViewSelectedBy属性不感兴趣,但是对它的子属性TypeName感兴趣,所以列必须定义在脚本块中。第三列也是脚本块。因为它的长度和列头冲突,一个用于格式化的哈希表应当应用到这里,允许你能选择列的标题。
提供给你的结果是一个可编辑的列表。第一列显示的是所有视图的名称;视图被适用的对象类型位于第二列;第三列展示这些格式化命令Format-Table, Format-List, Format-Wide 或者 Format-Custom那个会应用到它。
Name $_.ViewSelectedBy.TypeName Type ---- -------------------------- ---- System.Collections.DictionaryEntry System.Collections.DictionaryEntry List Dictionary System.Collections.DictionaryEntry Table System.Diagnostics.EventLog System.Diagnostics.EventLog Table System.Diagnostics.EventLog System.Diagnostics.EventLog List System.Diagnostics.EventLogEntry System.Diagnostics.EventLogEntry List System.Diagnostics.EventLogEntry System.Diagnostics.EventLogEntry Table System.Diagnostics.FileVersionInfo System.Diagnostics.FileVersionInfo Table System.Diagnostics.FileVersionInfo System.Diagnostics.FileVersionInfo List Priority System.Diagnostics.Process Table StartTime System.Diagnostics.Process Table process System.Diagnostics.Process Wide process System.Diagnostics.Process Table PSSnapInInfo System.Management.Automation.PSSnapInIn List fo PSSnapInInfo System.Management.Automation.PSSnapInIn Table fo System.Reflection.Assembly System.Reflection.Assembly List System.Reflection.Assembly System.Reflection.Assembly Table System.Security.AccessControl.ObjectSec System.Security.AccessControl.ObjectSec Table urity urity System.Security.AccessControl.ObjectSec System.Security.AccessControl.ObjectSec List urity urity service System.ServiceProcess.ServiceController Table System.ServiceProcess.ServiceController System.ServiceProcess.ServiceController List System.TimeSpan System.TimeSpan Wide System.TimeSpan System.TimeSpan List System.TimeSpan System.TimeSpan Table
记住这些包含格式化信息的XML文件。你只有在生成了所有格式化XML文件列表时,才可以得到一个完整的概览。
原文链接:Chapter 14. XML
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!
这个太深奥了点,看了半天没理解。
一句话ETS就是定义对象那些属性应当显示,那些属性应当隐藏。
比如:
为什么默认只显示Mode,LastWriteTime,Length,Name这几个属性? 谁规定的,就是ETS(扩展类型系统)配置的。