本文目录
PowerShell处理XML系列文章
如果你想将XML文件按照实际的XML来处理,而不是纯文本。文件的内容必须转换成XML类型。类型转换在第六章已经提到,只须一行。
$xmldata = [xml](Get-Content employee.xml)
Get-Content从之前保存的xml文件中读取xml内容,然后使用[xml]将xml内容转换成真正的XML。你可以将xml文本直接转换成XML,然后保存在变量$xml中:
$xmldata = [xml]$xml
然而,转换只会在指定的xml文本合法并不包含解析错误时有效。当你尝试转换的xml文件结构不合法,会报错。
用来描述XML的结构和信息现在被存放在变量$xmldata。从现在开始,获取一小段信息将会变得非常容易,因为XML对象将每个结点转换成了属性。你可以像这样获取员工信息:
$xmldata.staff.employee
Name Function Age ---- ----- ----- Tobias Weltner management 39 Cofi Heidecke security 4
访问和更新单个结点
如果一个结点在xml中是唯一的,你可以像前面的例子一样输入一个句号来访问它。然而,多数情况下XML文档包含了许多类似的结点(被称为兄弟结点),像前面最后一个例子中一样,包含了多个独立的员工。比如,你可以使用管道获得特定的员工,然后来更新它的数据。
$xmldata.staff.employee | Where-Object { $_.Name -match "Tobias Weltner" }
Name function age ---- -------- --- Tobias Weltner management 39
$employee = $xmldata.staff.employee | Where-Object { $_.Name -match "Tobias Weltner" } $employee.function = "vacation" $xmldata.staff.employee | ft -autosize
Name function age ---- -------- --- Tobias Weltner vacation 39 Cofi Heidecke security 4
使用SelectNodes()来选择Nodes
SelectNodes()方法是Xpath查询语言支持的方法,也允许你选择结点。XPath指的是一个结点‘路径名称’:
$xmldata = [xml](Get-Content employee.xml) $xmldata.SelectNodes("staff/employee")
Name function age ---- -------- --- Tobias Weltner management 39 Cofi Heidecke security 4
结果看起来像前面直接通过属性访问一样,但是XPath支持在方括号中使用通配符访问。下面的语句只会返回第一个员工结点。
PS> $xmldata.SelectNodes("staff/employee[1]") Name function age ---- -------- --- Tobias Weltner management 39
如果你想,你还可以获取一个年龄小于18岁的员工列表:
PS> $xmldata.SelectNodes("staff/employee[age<18]") Name function age ---- -------- --- Cofi Heidecke security 4
类似的方式,查询语言也支持获取列表中的最后一位员工信息,所以也可以指定位置:
$xmldata.SelectNodes("staff/employee[last()]") $xmldata.SelectNodes("staff/employee[position()>1]")
或者,你可以使用所谓的XpathNavigator,从中获取许多从XML文本的类型转换。
# 创建一个 XML定位: $xpath = [System.XML.XPath.XPathDocument]` [System.IO.TextReader][System.IO.StringReader]` (Get-Content employee.xml | out-string) $navigator = $xpath.CreateNavigator() # 输出Hanover子公司的最后一位员工 $query = "/staff[@branch='Hanover']/employee[last()]/Name" $navigator.Select($query) | Format-Table Value Value ----- Cofi Heidecke # 输出Hanover子公司的除了Tobias Weltner之外的所有员工, $query = "/staff[@branch='Hanover']/employee[Name!='Tobias Weltner']" $navigator.Select($query) | Format-Table Value Value ----- Cofi Heideckesecurity 4荔非苔注:如果你的XML文档包含命名空间,SelectNodes时稍有不同,可以参考这篇文章PowerShell 基于Namespace来SelectNode
访问属性
属性是定义在一个XML标签中的信息,如果你想查看结点的属性,可以使用get_Attributes()方法:
$xmldata.staff.get_Attributes() #text ----- Hanover sales
使用GetAttribute()方法来查询一个特定的属性:
$xmldata.staff.GetAttribute("branch") Hanover
使用SetAttribute()方法来指定新的属性,或者更新(重写)已有的属性。
$xmldata.staff.SetAttribute("branch", "New York") $xmldata.staff.GetAttribute("branch") New York
添加新结点
如果你想在员工结点列表中添加新的员工。首先,使用CreateElement()创建一个员工元素,然后定制员工的内部结构。最后,就可以在XML结构中你期望的位置插入这个元素。
# 加载XML文本文件: $xmldata = [xml](Get-Content employee.xml) # 创建新的结点: $newemployee = $xmldata.CreateElement("employee") $newemployee.set_InnerXML( ` "<Name>Bernd Seiler</Name><function>expert</function>") # 插入新结点: $xmldata.staff.AppendChild($newemployee) # 验证结果: $xmldata.staff.employee
Name function age ---- -------- --- Tobias Weltner management 39 Cofi Heidecke security 4 Bernd Seiler expert
# 输出为纯文本: $xmldata.get_InnerXml()
<?xml version="1.0"?><Branch office staff="Hanover" Type="sales"> <employee><Name>Tobias Weltner</Name><function>management</function> <age>39</age></employee><employee><Name>Cofi Heidecke</Name> <function>security</function><age>4</age></employee><employee> <Name>Bernd Seiler</Name><function>expert</function></employee></staff>
保存XML文件
$xmldata.Save(“$env:temp\updateddata.xml”)
原文链接:Chapter 14. XML
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!
广播: PowerShell处理XML(一)XML 结构 | PowerShell 中文博客
写得非常详细,很实用。
将对象保存到原xml文件的函数是:$xmldata.Save(“$env:temp\updateddata.xml”)
感谢Gavin,将你的例子更新在文章中了保存XML文件