4

I have an XML file. I need to replace the language with Swedish.

 <?xml version="1.0" encoding="utf-8"?>
    <usersettings>
      <Language type="string">English</Language>
    </usersettings>

Can you help me?

$xmldata = [xml] (Get-Content $file)
$xmldata.usersettings.Language.'#text'

2 Answers 2

4

Assign the new value to the InnerText attribute of the desired node:

$xmldata.usersettings.Language.InnerText = 'Swedish'

# remember to save updated document to disk
$xmldata.Save((Resolve-Path $file).Path)
Sign up to request clarification or add additional context in comments.

Comments

1

To complement Mathias R. Jessen's helpful answer:

Your own approach would have worked too - although it is (a) a bit more obscure, and (b) relies on the target element to already contain text (which is true in your case):

$xmldata.usersettings.Language.'#text' = 'Swedish'

PowerShell's adaptation of the XML DOM (surfacing child elements and attributes as properties) is handy, but remembering the precise rules can be tricky:

  • If a given element only has no content or only text content (a text child node) and also no attributes, it surfaces as a string-valued property on its parent element.

    • You can directly assign a string to such a property to set its text content; e.g.:

      $xml = [xml] '<usersettings><Language>English</Language></usersettings>'
      $xml.usersettings.Language = 'Swedish'
      $xml.OuterXml # output the XML for verification
      
  • By contrast, if an element has attributes and/or child elements, it surfaces as an XmlElement-valued property.

    • A child text node, if any, is represented as adapted property .'#text' (quoting needed), alongside adapted properties representing attributes and child elements, if any.

      $xml = [xml] '<usersettings><Language type="String">English</Language></usersettings>'
      # Due to presence of an *attribute*, assignment must now happen
      # via a property.
      # Property '#text' is the existing text child node (text content).
      $xml.usersettings.Language.'#text' = 'Swedish'
      $xml.OuterXml # output the XML for verification
      
    • Independently, you can use the type-native .InnerText property to replace an element's current child nodes, if any, with a text node, as shown in Mathias' answer.

      $xml = [xml] '<usersettings><Language type="String">English</Language></usersettings>'
      # Due to presence of an *attribute*, assignment must now happen
      # via a property.
      # Property .InnerText replaces all child nodes, if any, with 
      # a child text node (text content).
      $xml.usersettings.Language.InnerText = 'Swedish'
      $xml.OuterXml # output the XML for verification
      

In short:

  • When using PowerShell's property-based adaptation of the XML DOM, you need to be aware of when an XML element becomes a property of type [string] - to which you can assign a string directly - vs. when it becomes an XmlElement-typed property - which requires use of another property to assign text content.

  • That other property can be .'#text', if there's existing text content (a text child node) or - independently of any existing child nodes - .InnerText, but note that the latter quietly replaces any existing child nodes, including element child nodes.

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.