【问题标题】:How to iterate through a System.Array type object that comes from an XML?如何遍历来自 XML 的 System.Array 类型对象?
【发布时间】:2018-09-30 09:41:42
【问题描述】:

我是解析 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>

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

有人可以帮我吗?

【问题讨论】:

  • 我会尝试使用 XPath 来编写它。然后我可以使用Select-Xml

标签: xml powershell powershell-2.0


【解决方案1】:

您可以使用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"}

【讨论】:

  • 感谢您的回答。我试图让您提出的解决方案起作用,但我一直收到错误消息说: $Web.Configuration.location.'system.WebServer'.modules.AppendChild($RMNode.Clone()) 和 $Web.Configuration .location.'system.WebServer'.modules.RemoveChild($RMNode) 为空值。这是我得到的错误:您不能在空值表达式上调用方法。那里可能有什么问题?谢谢!
  • 我尝试手动将 RewriteModule 移动到 DynamicCompressionModule 上,以查看解决方案是否有效并收到这些错误。
  • 原来我必须为 Powershell 指定索引 [0] 以表明我正在使用 XML 对象而不是 System.Array。 System.Array 包含 XML 对象。谢谢大家 ! :)
  • $Web.Configuration.location.'system.WebServer'.modules[0].AppendChild($RMNode.Clone()) $Web.Configuration.location.'system.WebServer'.modules[ 0].RemoveChild($RMNode)
【解决方案2】:

您需要访问该对象。

($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 的模块名称。

【讨论】:

  • ($Web.Configuration.location.'system.WebServer'.modules.add.name) 没有给我一个列表。我得到一个包含“添加”的字符串。发生了什么?
猜你喜欢
  • 1970-01-01
  • 2014-02-19
  • 1970-01-01
  • 2013-03-11
  • 2021-07-21
  • 2015-06-14
  • 1970-01-01
  • 2019-12-14
  • 2012-03-08
相关资源
最近更新 更多