如何遍历来自 XML 的 System.Array 类型对象?

How to iterate through a System.Array type object that comes from an XML?

我是解析 XML 的 Powershell 脚本的新手,我只是 运行 遇到这样一种情况,我需要确保 XML 行在另一行之前严格执行。

为了到达那里,我首先搜索了我将如何阅读 XML 文件,这就是我得到的:

[XML]$Web = Get-Content *path_to_XML_file*

使用点符号,我到达了包含需要验证的行的节点(我仍然不知道我将如何设法找到行号以确定它是在另一行之前还是之后) .

我需要迭代的节点位于:

$Web.Configuration.location.'system.WebServer'.modules

这是我输入最后一行时的控制台输出:

add
---
{HttpCacheModule, DynamicCompressionModule, IsapiFilterModule, ProtocolSupportModule...}

此节点包含名为 'add' 但类型为 System.Array 的其他节点的多个实例。

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

此外,这是 XML 中模块节点的副本:

 <modules>
        <add name="HttpCacheModule" lockItem="true" />
            <add name="DynamicCompressionModule" lockItem="true" />   <--HERE
        <add name="IsapiFilterModule" lockItem="true" />
        <add name="ProtocolSupportModule" lockItem="true" />
        <add name="StaticFileModule" lockItem="true" />
        <add name="AnonymousAuthenticationModule" lockItem="true" />
        <add name="DefaultDocumentModule" lockItem="true" />
        <add name="CustomErrorModule" lockItem="true" />
        <add name="HttpRedirectionModule" lockItem="true" />
        <add name="RequestFilteringModule" lockItem="true" />
        <add name="IsapiModule" lockItem="true" />
        <add name="ConfigurationValidationModule" lockItem="true" />
            <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" preCondition="managedHandler" />
            <add name="Session" type="System.Web.SessionState.SessionStateModule" preCondition="managedHandler" />
            <add name="WindowsAuthenticationModule" lockItem="true" />
            <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" preCondition="managedHandler" />
            <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" preCondition="managedHandler" />
            <add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" preCondition="managedHandler" />
            <add name="RoleManager" type="System.Web.Security.RoleManagerModule" preCondition="managedHandler" />
            <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="managedHandler" />
            <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" preCondition="managedHandler" />
            <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" preCondition="managedHandler" />
            <add name="Profile" type="System.Web.Profile.ProfileModule" preCondition="managedHandler" />
            <add name="UrlMappingsModule" type="System.Web.UrlMappingsModule" preCondition="managedHandler" />
            <add name="BasicAuthenticationModule" lockItem="true" />
            <add name="HttpLoggingModule" lockItem="true" />
            <add name="StaticCompressionModule" lockItem="true" />
            <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler,runtimeVersionv2.0" />
            <add name="ServiceModel-4.0" type="System.ServiceModel.Activation.ServiceHttpModule, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler,runtimeVersionv4.0" />
            <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler,runtimeVersionv4.0" />
            <add name="ScriptModule-4.0" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler,runtimeVersionv4.0" />
            <add name="ClientLoggingHandler" />
            <add name="AdvancedLoggingModule" />
            <add name="AppWarmupModule" />
            <add name="RewriteModule" />  <---- HERE
            <add name="FailedRequestsTracingModule" lockItem="true" />
            <add name="F5XFFHttpModule" />
    </modules>

我需要确保 <add name="DynamicCompressionModule" lockItem="true" /> 行绝对在 <add name="RewriteModule" /> 之前执行,我不知道如何遍历此 System.Array 以到达那里。

有人可以帮我吗?

您需要访问该对象。

($Web.Configuration.location.'system.WebServer'.modules.add.name) 会给你一个列表。

然后您可以使用 Foreach-Object 或 foreach 循环。如果你想比较两个对象,你可以使用 .IndexOf('')

($Web.Configuration.location.'system.WebServer'.modules.add.name).IndexOf('DynamicCompressionModule') #should return 1 since it is second in the list (and arrays start at zero)

($Web.Configuration.location.'system.WebServer'.modules.add.name).IndexOf('RewriteModule') #should return 34

这将遍历列表并允许您对每个名称执行一些操作

foreach ($a in $Web.Configuration.location.'system.WebServer'.modules.add.name) { $a }

删除 'name' 将显示 'lockItem' 信息。

foreach ($a in $Web.Configuration.location.'system.WebServer'.modules.add) {
    if ($a.lockItem -eq $true) { 
            $a 
    } 
}

这将列出所有 lockItem 设置为 true 的模块名称。

您可以使用 NextSibling 属性 导航 add 节点。由于您的数组本身没有索引,我们只需要为您关心的项目建立索引,如果第二个在错误的位置,则将其移至末尾。当我们遍历节点时,我只是使用 $i 来计数,如果我们找到 DynamicCompressionModule 或 RewriteModule,我会得到它的索引,然后我会得到 RewriteModule 节点,这样我可以在以后需要时移动它。然后如果 DynamicCompressionModule 的索引大于 RewriteModule 的索引,我在数组的最后一个节点之后添加一个 RewriteModule 的克隆,并删除原来的。

$i=0
$CurrentNode = $Web.Configuration.location.'system.WebServer'.modules.FirstChild

Do{
    $i
    $CurrentNode
    Switch($CurrentNode){
        {$_.Name -eq 'DynamicCompressionModule'}{$DCM=$i;$DCMNode=$CurrentNode}
        {$_.Name -eq 'RewriteModule'}{$RM=$i;$RMNode=$CurrentNode}
    }
    $i++
    $CurrentNode = $CurrentNode.NextSibling

}Until($CurrentNode -eq $Web.Configuration.location.'system.WebServer'.modules.LastChild)

If($DCM -gt $RM){
    "Moving RewriteModule to end of list"
    #Add a clone of the RewriteModule node after the last item in the 'add' array
    $Web.Configuration.location.'system.WebServer'.modules.AppendChild($RMNode.Clone())
    #Remove the original RewriteModule node since we now have a clone of it at the end of the array
    $Web.Configuration.location.'system.WebServer'.modules.RemoveChild($RMNode)
}Else{"No change needed"}