8

Okay, so here is the snippet of my web.config file:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<location path="." inheritInChildApplications="false">
<connectionStrings>
...
</connectionStrings>
</location>
<location path="." inheritInChildApplications="false">
<appSettings>
<!--IT Ops-->
<add key="SomeOtherKey" value="SomeOtherValue" />
<add key="SiteDomain" value="somedomain.com" />
<add key="SomeOtherKey" value="SomeOtherValue" />
....
</appSettings>
</location>
</configuration>

What I'm trying to do is find the node using xPath via Powershell. A couple things to note about this XML file:

there are multiple:

<location path="." inheritInChildApplications="false"> 

values in the xml file. They surround other nodes like etc...

I can find and replace the connection string values successfully using this script

$WebConfigFile = Join-Path $destination Web.config
[xml]$WebConfigXml = Get-Content ($WebConfigFile)
$WebConfigXml.configuration.location[2].connectionStrings.add | % { $_.connectionString = $_.connectionString -replace "some value", $sqlServerName }

But when I go to replace the add key="SiteDomain" value using this script:

$node = $WebConfigXml.configuration.location[3].appSettings.SelectSingleNode("add[@key = 'SiteDomain']")
$node.value = "someValue"
$WebConfigXml.Save($WebConfigFile)

it does not work. The $node value in this case contains an empty string.

I'm also trying just to read the node like this:

$appSettingsSection = $WebConfigXml.configuration.location[3].appSettings;
$existingSiteDomain = $appSettingsSection.SelectSingleNode("add[@key='SiteDomain']")

And I'm still getting an empty string for the $existingSiteDomain value.

I've looked at samples using SelectSingleNode and I can't quite seem to figure it out. Not too sure what I'm doing wrong.

Thanks, Mike

2 Answers 2

24

Your XML file has a namespace:

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">

so you need a namespace manager for SelectSingleNode (see section "Remarks"):

XPath expressions can include namespaces. Namespace resolution is supported using the XmlNamespaceManager. If the XPath expression includes a prefix, the prefix and namespace URI pair must be added to the XmlNamespaceManager.

Something like this should work:

$ns = New-Object System.Xml.XmlNamespaceManager($WebConfigXml.NameTable)
$ns.AddNamespace("ns", $WebConfigXml.DocumentElement.NamespaceURI)
$node = $WebConfigXml.SelectSingleNode("//ns:add[@key='SiteDomain']", $ns)
Sign up to request clarification or add additional context in comments.

2 Comments

Okay, I tried that, but now I'm getting an error from Powershell. It doesn't know XmlNamespaceManager is: "XmlNamespaceManager : The term 'XmlNamespaceManager' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.". I ran "$psversiontable.psversion" on the powershell command line and it says I have Powershell version 3.0 installed. Is this some type of versioning problem?
Okay, I amend my previous comment. It is now working. I think there was some other syntax issue in my script that was causing this error. The code you provided worked! Thanks so much. I'm new to Powershell and xPath, so I had no idea about this namespace issue.
1

Other alternative can be by using Select-Xml cmdlet:

$nameSpace = @{ x=$WebConfigXml.DocumentElement.NamespaceURI }    
$result = Select-Xml -Xml $WebConfigXml -XPath "//ns:add[@key='SiteDomain']" -Namespace $nameSpace

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.