【问题标题】:Powershell not displaying every node in xmlPowershell不显示xml中的每个节点
【发布时间】:2015-03-25 13:07:36
【问题描述】:

我试图在 XML 文件中显示每个子节点,但有些节点没有显示。下面是我的 powershell 脚本。

$dst_web_config = "C:\Users\vel\web.config"
$src_web_config = "f:\Script_test\web.config"

# Creating XML objects for live and integration
$src_xml = New-Object -TypeName XML
$dst_xml = New-Object -TypeName XML
$src_xml.Load($src_web_config)
$dst_xml.Load($dst_web_config)

# Check nodes available
$src_top_node = $src_xml.DocumentElement.Name
$dst_top_node = $dst_xml.DocumentElement.Name

# Defining recursive function
function compare_nodes($node)
{
    if ($dst_xml.$dst_top_node.$node.HasChildNodes)
    {
        $dst_xml.SelectNodes("$dst_top_node/$node/*") | Select-Object -Expand Name | % {
            $xpath_node = [string]$node + "/" + [string]$_
            $path_node = [string]$node + "." + [string]$_
            write-host $path_node
            compare_nodes($path_node)
        }
    }
    else
    {
        #write-host "No Child found for" $node
        return
    }
}

if ($src_top_node -eq $dst_top_node)
{
    if ($dst_xml.$dst_top_node.HasChildNodes)
    {
        #write-host "Child Node exist for " $dst_top_node
        $dst_xml.SelectNodes("$dst_top_node/*") | Select-Object -Expand Name | % {
        compare_nodes($_)   
        }
    }
    else
    {
        write-host "No child nodes for "$dst_top_node
    }
}
else
{
    write-host $src_top_node" is not present in destination file"
}

我将 XML 文件的某些部分放置在未显示所有子节点的位置。

<configuration>
  <configSections>
    <section name="siteMapConfiguration" type="NRI.Helpers.Configuration.SiteMapConfiguration, NRI.Helpers" />
    <section name="promotionCategoriesSection" type="NRI.Helpers.Configuration.PromotionCategoriesConfigurationSection, NRI.Helpers" />
    <section name="BaseRestExtensions" type="domino.Web.BaseRest.Configuration.BaseRestSection, domino" requirePermission="false" />
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
    <section name="townSearchSection" type="NRI.Helpers.Configuration.SearchConfigurationSection, NRI.Helpers" />
    <section name="userTypesSection" type="NRI.Helpers.Configuration.UserTypesConfigurationSection, NRI.Helpers" />
  </configSections>
  <system.net>
    <mailSettings>
      <smtp>
        <network host="127.0.0.1" userName="username" password="password" />
      </smtp>
    </mailSettings>
  </system.net>

在脚本输出中,我没有从上面的 xml 中获得“sectionGroup”、“smtp”。这是两个典型的例子。如何确保脚本显示所有子节点?

【问题讨论】:

    标签: xml powershell


    【解决方案1】:

    问题

    这里发生了几件事。

    首先,当我使用您的代码运行时,我得到了sectionGroup。但是我看到它显示为configSections.system.web.webPages.razor,因为该节点有一个名称,并且您在管道中使用Select-Object -Expand Name

    其次,虽然它没有引起问题,但您的函数调用语法不正确。 compare_nodes($_) 应该是 compare_nodes $_compare_nodes($path_node) 应该是 compare_nodes $path_node。如果您添加更多参数,这真的会让您感到困惑,因为 myfunc($a, $b) 与 PowerShell 中的 myfunc $a $b 非常不同。

    最后,您的算法在smtp 的情况下不起作用,因为您有一个名称中带有. 的元素。当您使用等于"system.net.mailSettings"$node 进行递归时,您对HasChildNodes 的测试将失败。

    if ($dst_xml.$dst_top_node.$node.HasChildNodes)
    

    对此进行评估:

    if ($dst_xml.$dst_top_node."system.net.mailsettings".HasChildNodes)
    

    代替:

    if ($dst_xml.$dst_top_node."system.net".mailsettings.HasChildNodes)
    

    您可以通过运行以下命令对其进行测试:

    $dst_xml.$dst_top_node."system.net.mailsettings"
    $dst_xml.$dst_top_node."system.net".mailsettings
    

    解决方案

    重写这是不平凡的。我建议使用 XmlNode 对象本身,然后将第二个参数与路径一起传递(仅用于您的输出)。例如,

    function compare_nodes($node, $fullpath) {
        $node.ChildNodes | % {
            # build up $new_fullpath from $fullpath here
            compare_nodes $_ $new_fullpath
        }
    }
    
    if ($dst_xml.$dst_top_node.HasChildNodes) {
        $dst_xml.$dst_top_node.ChildNodes | % {
            compare_nodes $_ $dst_top_node
        }
    }
    

    【讨论】:

    • 如果我知道那里有多少个节点,我就可以做到。我必须列出文件中我不知道结构有多深的所有节点。
    • 是的,我看到我的回答在那种情况下是没用的。有什么理由不能使用Compare-Object $(Get-Content C:\Users\vel\web.config) $(Get-Content f:\Script_test\web.config)?我正在尝试了解您要解决的问题。
    • 这两个文件属于不同的环境。我试图在节点级别比较它们。要求是每个节点都必须出现在两个文件中,它们的值可能因环境而异。
    • 感谢 Swoogan 投入您的时间。在您提供的解决方案中,我们在哪里检查我们是否已经到达节点链的底部(没有更多的子节点)?您是否要求将该检查与 new_fullpath 创建逻辑一起进行?
    • 只要你只使用Write-Host而不返回任何东西,你就不需要。在您的初始代码中,else { return } 是多余的;该函数在没有它的情况下返回。在我的例子中,函数在处理完 ChildNodes 或者首先没有要处理时返回。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    相关资源
    最近更新 更多