thomasb
thomasb

Reputation: 6035

Select an attribute with Xpath in a XML with namespace using Powershell

I have a .Net config file with a NLog node inside:

<?xml version="1.0"?>
<configuration>
  <appSettings>
  </appSettings>
  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets async="true">
      <target xsi:type="File" name="f" fileName="path to file" />
    </targets>
    <rules>
      <logger name="*" minlevel="Debug" writeTo="c,f" />
    </rules>
  </nlog>
</configuration>

I'm trying to change the target's fileName value using Powershell.

I'm using this code:

[xml]$xml = Get-Content $file
$ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
$ns.AddNamespace("ns", $namespace) # $namespace is `http://www.nlog-project.org/schemas/NLog.xsd`
$values = $xml.selectNodes($xpath, $ns)

My XPath expression is //ns:nlog/ns:targets/ns:target[@ns:name='f']/@ns:fileName

But $values always has 0 results.

Any idea ? What am I doing wrong ?

Thanks !

Upvotes: 2

Views: 3163

Answers (1)

Mathias M&#252;ller
Mathias M&#252;ller

Reputation: 22637

In your XML document, there is a default namespace:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd">

Descendant elements are then implicitly prefixed with this namespace. However, attributes do not take on a default namespace. In other words, the attribute in your input XML is not called ns:fileName, but only fileName. The same applies to the name attribute.

//ns:nlog/ns:targets/ns:target[@name='f']/@fileName

Depending on the structure of your XML (and its predictability) you might want to shorten the expression to

//ns:target[@name='f']/@fileName

To make your intial XPath expression work, the input XML would have to look like:

<targets xmlns:ns="http://www.nlog-project.org/schemas/NLog.xsd" async="true">
  <target xsi:type="File" ns:name="f" ns:fileName="path to file" />
</targets>

Upvotes: 3

Related Questions