web-dev-qa-db-fra.com

Modifier la valeur de l'élément XML avec PowerShell

Je ne trouve que des informations sur la façon de modifier les valeurs d'attribut d'un élément XML ici sur StackOverflow.

Mais comment pouvons-nous changer la valeur de l'élément lui-même à l'aide de PowerShell?

J'ai actuellement:

[~ # ~] 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)

Cependant, je n'arrive pas à utiliser des méthodes sur la dernière variable. Qu'est-ce que je fais mal?

Modifier

  • Code ajouté

L'erreur que je reçois est Vous ne pouvez pas appeler une méthode sur une expression de valeur nulle

Je pense que mon problème réside dans:

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

Ce qui reste nul, mais j'ai essayé des méthodes comme .SelectNodes et jouer avec le //Argumentstag mais toujours pas de succès

7
Kahn Kah

InnerText est une propriété, pas une méthode. Il est utilisé comme ceci:

$element.InnerText = "newtext"

En outre, je soupçonne que vos données d'origine (contrairement à l'exemple XML que vous avez publié) utilisent des espaces de noms. AFAICS c'est la seule raison possible pour laquelle $xml.SelectSingleNode('//Arguments') retournerait un résultat vide. Les fichiers XML exportés à partir du Planificateur de tâches Windows sont définitivement à espace de noms:

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

Les espaces de noms ne sont pas comme les autres attributs de nœud et affectent non seulement le nœud lui-même, mais aussi ses nœuds enfants. Pour sélectionner des nœuds dans un XML avec des espaces de noms, vous avez besoin d'un gestionnaire d'espaces de noms :

$nsm = New-Object Xml.XmlNamespaceManager($xml.NameTable)
$nsm.AddNamespace('ns', $xml.DocumentElement.NamespaceURI)
$element = $xml.SelectSingleNode('//ns:Arguments', $nsm)
12
Ansgar Wiechers

Quand je cours:

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

Et revérifiez la sortie, je vois la valeur mise à jour:

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

J'ai mis le chemin entre guillemets, sinon j'obtenais une erreur sur la ligne de chargement. C'est de toute façon une bonne pratique, car le paramètre de la méthode Load prend string filepath en entrée. Puis, comme le mentionne Ansgar, utilisez l'opérateur d'affectation ("=") pour définir la nouvelle valeur en mémoire, puis effectuez un vidage dans un fichier.

5
Dave_J