1
votes

I trying to display every child node in an XML file but some nodes are not getting displayed. Below is my powershell script.

$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"
}

I am putting some sections of XML file where all child nodes are not getting displayed.

<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>

In script output I am not getting "sectionGroup", "smtp" from above xml. These are two typical examples. How can I make sure script displays all the child nodes?

1

1 Answers

0
votes

Problems

There are several things going on here.

First, when I run with your code, I am getting the sectionGroup. However I see it appearing as configSections.system.web.webPages.razor because the node has a name and you are using Select-Object -Expand Name in your pipeline.

Second, although it's not causing an issue, your function calling syntax is incorrect. compare_nodes($_) should be compare_nodes $_ and compare_nodes($path_node) should be compare_nodes $path_node. If you add more arguments, this will really mess you up because myfunc($a, $b) is very different from myfunc $a $b in PowerShell.

Finally, your algorithm is not working in the case of smtp, because you have an element with a . in the name. When you recurse with $node equal to "system.net.mailSettings" your test of HasChildNodes fails.

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

is evaluating to this:

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

instead of:

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

You can test it by just running the following:

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

Solution

Rewriting this is non-trivial. I would suggest using the XmlNode objects themselves and then passing along a second argument with the path (just for your output). For example,

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
    }
}