[玩转系统] PowerShell 解析、读取和验证 XML 的魔力
作者:精品下载站 日期:2024-12-14 13:04:24 浏览:15 分类:玩电脑
PowerShell 解析、读取和验证 XML 的魔力
XML 无处不在。尽管尖括号的使用很烦人,XML 格式仍然被广泛使用。配置文件、RSS 源、Office 文件(.docx 中的“x”)只是部分列表。使用 PowerShell 解析 XML 文件是 PowerShell 之旅中的重要一步。
本教程将向您展示 PowerShell 如何解析 XML 文件并验证它们。这将引导您从零到精通获取和评估 XML 数据的各个方面。您将获得一些工具,帮助您验证 XML 数据完整性并在脚本门口阻止错误数据!
先决条件
要遵循所提供的材料,您应该:
- PowerShell 版本 3.0 及更高版本。这些示例是在 Windows PowerShell v5.1 上创建的
- Notepad++、Visual Studio Code 或其他理解 XML 的文本编辑器。
使用 Select-Xml
解析 Powershell XML 元素
让我们首先介绍使用 PowerShell 解析 XML 的最流行和最简单的方法之一,即使用 Select-Xml
。 Select-Xml
cmdlet 允许您提供 XML 文件或字符串以及称为 XPath 的“过滤器”,以提取特定信息。
XPath 是一个元素名称链。它使用“类似路径”语法来识别和导航 XML 文档中的节点。
假设您有一个包含多台计算机的 XML 文件,并且希望使用 PowerShell 来解析该 XML 文件。每台计算机都有各种元素,例如名称、IP 地址和用于包含在报告中的 Include
元素。
元素是带有开始标记和结束标记的 XML 部分,中间可能有一些文本,例如 SRV-01
<Computers>
<Computer>
<Name>SRV-01</Name>
<Ip>127.0.0.1</Ip>
<Include>true</Include>
</Computer>
<Computer>
<Name>SRV-02</Name>
<Ip>192.168.0.102</Ip>
<Include>false</Include>
</Computer>
<Computer>
<Name>SRV-03</Name>
<Ip>192.168.0.103</Ip>
<Include>true</Include>
</Computer>
</Computers>
您想使用 PowerShell 解析此 XML 文件以获取计算机名称。为此,您可以使用 Select-Xml
命令。
在上面的文件中,计算机名称出现在 Name 元素的内部文本 (InnerXML) 中。
InnerXML 是两个元素标签之间的文本。
要查找计算机名称,您首先需要提供适当的 XPath (/Computers/Computer/Name
)。此 XPath 语法将仅返回 Computer
元素下的 Name
节点。然后,要仅获取每个 Name
元素的 InnerXML,请使用 ForEach-Object
循环访问每个元素的 Node.InnerXML
属性。
Select-Xml -Path C:\Work\computers-elm.xml -XPath '/Computers/Computer/Name' | ForEach-Object { $_.Node.InnerXML }
使用 PowerShell 通过 Select-Xml
解析 XML 属性
现在让我们从不同的角度解决查找计算机名称的问题。这次,计算机描述符不再用 XML 元素 表示,而是用 XML 属性 表示。
属性是键/值部分,例如 name="SRV-01"
。属性始终出现在开始标记内,位于标记名称之后。
下面是带有用属性表示的计算机描述符的 XML 文件。您现在可以将每个描述符视为属性而不是元素。
<Computers>
<Computer name="SRV-01" ip="127.0.0.1" include="true" />
<Computer name="SRV-02" ip="192.168.0.102" include="false" />
<Computer name="SRV-03" ip="192.168.0.103" include="true" />
</Computers>
由于这次每个描述符都是一个属性,因此请稍微调整 XPath 以仅查找 Computer 元素。然后,再次使用 ForEach-Object
cmdlet 查找 name 属性的值。
Select-Xml -Path C:\Work\computers-attr.xml -XPath '/Computers/Computer' | ForEach-Object { $_.Node.name }
事实上,这也带来了相同的结果:SRV-01、SRV-02 和 SRV-03:
在这两种情况下,无论您是读取元素还是属性,Select-Xml
的语法都很麻烦:它强制您使用 XPath
参数,然后将结果通过管道传递给一个循环,最后查找 Node 属性下的数据。
幸运的是,PowerShell 提供了一种更方便、更直观的方式来读取 XML 文件。 PowerShell 允许您读取 XML 文件并将其转换为 XML 对象。
相关:使用 PowerShell 数据类型加速器加速编码
将 XML 字符串转换为对象
使用 PowerShell 解析 XML 的另一种方法是将 XML 转换为对象。最简单的方法是使用 [xml]
类型加速器。
通过在变量名称前添加 [xml]
前缀,PowerShell 会将原始纯文本 XML 转换为您可以使用的对象。
[xml]$xmlElm = Get-Content -Path C:\Work\computers-elm.xml
[xml]$xmlAttr = Get-Content -Path C:\Work\computers-attr.xml
读取 XML 对象元素
现在,$xmlElm
和 $xmlAttr
变量都是 XML 对象,允许您通过点表示法引用属性。也许您需要找到每个计算机元素的 IP 地址。由于 XML 文件是一个对象,因此您可以通过简单地引用 IP 元素来实现。
$xmlElm.Computers.Computer.ip
从 PowerShell 3.0 版开始,XML 对象使用与读取元素内部文本相同的语法来获取属性值。因此,IP 地址的值是从属性文件中读取的,其语法与元素文件完全相同。
读取 XML 属性
使用完全相同的点表示法,您也可以读取 XML 属性,尽管 XML 结构存在差异。
$xmlElm.Computers.Computer.ip
$xmlAttr.Computers.Computer.ip
下面的结果表明两者都获得了相同的数据,每个数据都来自其相应的文件:
此外,对于该对象,一旦将其加载到内存中,如果您使用的是 PowerShell ISE,您甚至可以使用 IntelliSense 进行制表符补全。例如如下所示。
迭代 XML 数据
一旦您成功将 XML 文件直接读取为 XML 对象(通过利用 [xml]
类型加速器),您就拥有了 PowerShell 对象的全部功能。
例如,您需要循环遍历 XML 文件中包含 include=”true” 属性的所有计算机,以检查它们的连接状态。下面的代码展示了如何做到这一点。
这个脚本是:
- 读取文件并将其转换为 XML 对象。
- 迭代相关计算机以获取其连接状态。
- 最后将结果输出对象发送到管道。
## casting the file text to an XML object
[xml]$xmlAttr = Get-Content -Path C:\Work\computers-attr.xml
## looping through computers set with include="true"
$xmlAttr.Computers.Computer | Where-Object include -eq 'true' | ForEach-Object {
## see if the current computer is online
if(Test-Connection -ComputerName $_.ip -Count 1 -Quiet)
{
$status = 'Connection OK'
}
else
{
$status = 'No Connection'
}
## output the result object
[pscustomobject]@{
Name = $_.name
Ip = $_.ip
Status = $status
}
}
上面脚本的结果如下所示:
XML模式
在上一节中,您看到了两个不同的 XML 文件以两种不同的方式表示数据集。这些方式称为 XML 模式。 XML 模式定义特定 XML 文档的合法构建块:
- 可以出现在该特定文档中的元素和属性的名称。
- 子元素的数量和顺序。
- 元素和属性的数据类型。
该模式本质上定义了 XML 的结构。
验证 XML 数据
XML 文件可能具有正确的语法(如果语法不正确,Notepad++ 等编辑器会抱怨),但其数据可能与项目要求不匹配。这就是模式发挥作用的地方。当您依赖 XML 数据时,您必须确保所有数据根据定义的架构都是有效的。
您最不想看到的就是在运行时发现脚本中间 500 行深处的数据错误。到那时,它可能已经对文件系统和注册表执行了一些不可逆的操作。
那么,如何提前检查数据是否正确呢?让我们首先看看一些可能的错误类型。
XML 数据中可能出现的错误
一般来说,在 XML 文件上发现的错误属于以下两类之一:元数据错误和数据本身的错误。
XML 元数据错误
下面的这个文件 MorePeople.xml 在语法方面是完全有效的。您可以在下面看到该文件有一个 People 元素(根元素),其中包含三个 Person 元素。这种结构是完全可以接受的。尽管如此,它还是有一个例外,你能看到吗?
<People>
<Person Name="Debra" County="Canada" IsAdmin="true" />
<Person Name="Jacob" Country="Israel" IsAdmin="true" />
<Person Name="Olivia" Country="Cyprus" IsAdmin="false" />
</People>
如果没有,请不要担心,它只是隐藏起来了。问题出现在第一个内部元素中:
本来应该是一个国家的地方被拼写错误,加拿大被降级为县。
XML 数据中的错误
修复了 MorePeople.xml 上的 Country 问题后,又出现了另一个问题:
<People>
<Person Name="Debra" Country="Canada" IsAdmin="yes" />
<Person Name="Jacob" Country="Israel" IsAdmin="true" />
<Person Name="Olivia" Country="Cyprus" IsAdmin="false" />
</People>
元数据,即元素和属性,都很好。那么有什么问题吗?这次,问题再次发生在第一行 Person 上,出现在其中一个值中。有人认为 yes 足以替代 true - 但像下面这样的代码将无法获取第一个元素,因为它正在寻找 true ,不适合是:
$peopleXml.People.Person | Where-Object IsAdmin -eq 'true'
创建 XML 架构
现在您已经知道可能发生的错误类型,现在是时候展示架构文件如何提供帮助了。第一步是创建示例数据文件。该样本可以是最小的示例,并且只包含单个内部元素。对于上面的示例,让我们创建一个如下所示的示例文件 People.xml :
<People>
<Person Name="Jeff" Country="USA" IsAdmin="true" />
</People>
现在在下面构建一个 PowerShell 函数,并将其与示例数据一起使用来创建 .xsd 架构。
function New-XmlSchema
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory)]
[ValidateScript({ Test-Path -Path $_ })]
[ValidatePattern('\.xml')]
[string]$XmlExample
)
$item = Get-Item $XmlExample
$dir = $item.Directory
$name = $item.Name
$baseName = $item.BaseName
## build the schema path by replacing '.xml' with '.xsd'
$SchemaPath = "$dir$baseName.xsd"
try
{
$dataSet = New-Object -TypeName System.Data.DataSet
$dataSet.ReadXml($XmlExample) | Out-Null
$dataSet.WriteXmlSchema($SchemaPath)
## show the resulted schema file
Get-Item $SchemaPath
}
catch
{
$err = $_.Exception.Message
Write-Host "Failed to create XML schema for $XmlExample`nDetails: $err" -ForegroundColor Red
}
}
将该函数复制到您的 ISE 或您最喜欢的 Powershell 编辑器,将其加载到内存中并使用它来创建架构。加载函数后,创建模式的代码如下:
New-XmlSchema -XmlExample 'C:\Work\People.xml'
结果将显示新创建的架构的路径:
使用架构文件验证您的数据
看一下上面结果指定的位置。如果 .xsd 存在,那么您就可以正确地查看正在执行的验证。对于确认步骤,请使用以下函数:
function Test-XmlBySchema
{
[CmdletBinding()]
[OutputType([bool])]
param
(
[Parameter(Mandatory)]
[ValidateScript({ Test-Path -Path $_ })]
[ValidatePattern('\.xml')]
[string]$XmlFile,
[Parameter(Mandatory)]
[ValidateScript({ Test-Path -Path $_ })]
[ValidatePattern('\.xsd')]
[string]$SchemaPath
)
try
{
[xml]$xml = Get-Content $XmlFile
$xml.Schemas.Add('', $SchemaPath) | Out-Null
$xml.Validate($null)
Write-Verbose "Successfully validated $XmlFile against schema ($SchemaPath)"
$result = $true
}
catch
{
$err = $_.Exception.Message
Write-Verbose "Failed to validate $XmlFile against schema ($SchemaPath)`nDetails: $err"
$result = $false
}
finally
{
$result
}
}
将函数加载到内存,并使用它来验证两个错误示例中的 MorePeople.xml。要触发验证,请使用以下命令:
Test-XmlBySchema -XmlFile 'C:\Work\MorePeople.xml' -SchemaPath 'C:\Work\People.xsd' -Verbose
实际结果取决于MorePeople.xml 的内容。
让我们看两个例子。请注意,当 MorePeople.xml 没有错误时,上面的函数将返回 True。
当 MorePeople.xml 文件包含错误数据(Country 键拼写为 County)时,该函数将返回一些失败详细信息并返回 错误
。
正如您所看到的,详细输出中指定的错误信息非常丰富:它指向罪魁祸首文件并指向其中发生问题的确切组件。
微调验证模式
让我们看一下架构文件,然后看看如何使其变得更好。
默认情况下由 New-XmlSchema
创建的架构如下:
<?xml version="1.0" standalone="yes"?>
<xs:schema id="People" xmlns="" xmlns:xs="<http://www.w3.org/2001/XMLSchema>" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="People" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Person">
<xs:complexType>
<xs:attribute name="Name" type="xs:string" />
<xs:attribute name="Country" type="xs:string" />
<xs:attribute name="IsAdmin" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
上面的默认模式很好,但并不完美。事实上,它发现了 Country 属性的拼写错误。但是,如果您按原样保留架构,以防未满足您可能的其他期望 - Test-XmlBySchema
验证不会将这些问题报告为错误。让我们解决这个问题。
下表列出了一些不被视为验证错误并且会被 Test-XmlBySchema
忽视的情况。在每一行上,右列显示如何手动更改架构以添加对必要保护的支持。
架构文件的修改版本(添加了所有保护)显示在表格后面。
将设置添加到默认架构 - 示例
Required Behavior架构文件的相关设置
At least one Person element将 Person 元素的 minOccurs 值设置为 1
Make Name, Country and IsAdmin attributes mandatory将 use=”required” 添加到每个属性声明中
Allow only true/false values for IsAdmin为 IsAdmin 声明设置 type=”xs:boolean”
Allow only Country names between 3 and 40 characters使用xs:restriction (请参阅架构文本后的详细说明)
<?xml version="1.0" standalone="yes"?>
<xs:schema id="People" xmlns="" xmlns:xs="<http://www.w3.org/2001/XMLSchema>" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="People" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Person">
<xs:complexType>
<xs:attribute name="Name" type="xs:string" use="required" />
<xs:attribute name="Country" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="3"/>
<xs:maxLength value="40"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="IsAdmin" type="xs:boolean" use="required" />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
由于示例中的 IsAdmin 属性存在布尔值限制,其值必须为小写true 或 false。
使用 xs:restriction 验证字符串长度
字符串长度验证有点复杂。因此,尽管它在上面显示为修改后的架构的一部分,但它还是值得更多关注。
Country 属性的原始架构项(手动添加 use=”required” 后) 如下:
<xs:attribute name="Country" type="xs:string" use="required" />
要添加长度保护,您应该添加 元素,并在其中添加
。此限制又包含在
xs:minLength
和 xs:minLength
上声明的所需限制。
经过所有这些更改,最终的 xs:attribute
声明已从单行增长到巨大的 8 行节点:
<xs:attribute name="Country">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="3"/>
<xs:maxLength value="40"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
如果您在完成上述解释后没有感到头晕,那么您就有权查看正在执行的验证。为此,我们有意将值 Canada 缩短为两个字符的音节:Ca
设置好国家/地区短名称并保存 MorePeople.xml 后,您就可以运行下面的验证命令:
Test-XmlBySchema -XmlFile 'C:\Work\MorePeople.xml' -SchemaPath 'C:\Work\People.xsd' -Verbose
结果确实表明复杂的模式已经完成了它的工作:
XML 模式验证的复杂性可能会增加,并且可以验证您能想到的任何模式,尤其是与正则表达式结合使用时。
相关:PowerShell 和 Regex 入门
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag