21

I'm only finding stuff on how to change the attribute values of a XML element here on StackOverflow.

But how do we change the value of the element itself using PowerShell?

I currently have:

XML

<Task>
  <Settings>
  ...
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>blablabla</Command>
      <Arguments>CHANGETHISVALUE</Arguments>
    </Exec>
  </Actions>
</Task>

SCRIPT

$filePathToTask = C:\Task.xml
$xml = New-Object XML
$xml.Load($filePathToTask)
$element =  $xml.SelectSingleNode("//Arguments")
$element.InnerText("newtext")
$xml.Save($filePathToTask)

However, I can't seem to use methods on the last variable. What am I doing wrong?

Edit

  • Added code

The error that I'm getting is You cannot call a method on a null-valued expression

I think my problem lies at:

$ElementToChange =  $xml.SelectSingleNode("//Arguments")

Which stays null, but I have tried methods like .SelectNodes and playing around with the //Argumentstag but still no success

2
  • If you want us to tell you what you're doing wrong, you need to tell us what yo do. And what error that produces. Commented Mar 9, 2017 at 16:15
  • I'm sorry @AnsgarWiechers , I thought my mistake was maybe obvious by only the code (like usual when I post something) but you're right, I will edit it now Commented Mar 9, 2017 at 16:16

2 Answers 2

34

InnerText is a property, not a method. It's used like this:

$element.InnerText = "newtext"

Also, I suspect that your original data (unlike the XML sample you posted) uses namespaces. AFAICS that's the only possible reason why $xml.SelectSingleNode('//Arguments') would return an empty result. XML files exported from the Windows Task Scheduler definitely are namespaced:

<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task‌​">
  <!-- ... -->
</Task>

Namespaces are not like other node attributes and affect not only the node itself, but also its child nodes. For selecting nodes from an XML with namespaces you need a namespace manager:

$nsm = New-Object Xml.XmlNamespaceManager($xml.NameTable)
$nsm.AddNamespace('ns', $xml.DocumentElement.NamespaceURI)
$element = $xml.SelectSingleNode('//ns:Arguments', $nsm)
Sign up to request clarification or add additional context in comments.

Comments

10

When I run:

$filePathToTask = "C:\temp\Task.xml"
$xml = New-Object XML
$xml.Load($filePathToTask)
$element =  $xml.SelectSingleNode("//Arguments")
$element.InnerText = "New Text"
$xml.Save($filePathToTask)

And re-check the output, I do see the updated value:

<Task>
  <Settings>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>blablabla</Command>
      <Arguments>New Text</Arguments>
    </Exec>
  </Actions>
</Task>

I enclosed the path in quotes, otherwise I was getting an error on the load line. That's good practice anyway, since the parameter for the Load method takes string filepath as input. Then as Ansgar mentions, use the assignment operator ("=") to set the new value in memory, then dump to file.

2 Comments

Thanks, but what do you mean with "dump to file" ? You just mean save it or?
Yes, I mean "Write to disk"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.