-2

Let me preface by saying I have limited powershell experience and would gladly accept alternative applications for my needs.

I have an xml file with the following example:

<!-- ... -->
<anElement tag1="A" tag2="B" tag3="0.00" tag4="2.00" />
<anotherElement tag1="C" tag2="B" tag3="0.00" tag4="2.00" />
<somethingElse tag1="D" tag2="B" tag3="0.00" tag4="2.00">maybe some text here?</somethingElse>
<!-- ... -->

What I want to happen is:

If tag1 = A or D
And tag2 = B
then set tag3 value = tag4 value

So this would take lines 1 and 3 and update tag3 to be 2.00

So complete code I would need is: open file perform edits save file

JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
Kwixotic
  • 1
  • 1
  • 1
    What you show here is not an XML file. Please show an actual input file and what exactly the output would look like in that case. More help: http://stackoverflow.com/help/mcve. – Mathias Müller Feb 22 '17 at 19:37
  • well, what have you tried, what doesn't work? – 4c74356b41 Feb 22 '17 at 19:37
  • We are a community to help programmers and programming enthusiasts. That being said, it is expect that you show what you have done or tried before posting. This gives us something to build on. As of now this reads like a code writing request which is off topic for SO. Break your question into its parts and search individually for solutions to those problems. Then, if you are still having issues, please [edit] your question showing your work so we can better help you and the community. – Matt Feb 22 '17 at 19:45
  • Sorry, I'm new to SO and to powershell. I can piece together different pieces but don't know how to format in powershell. I used the following regex to find the lines impacted: A[^<>]+tag3="0 I know how to write if then's in sql but wasn't sure how to translate the aforementioned regex, along with the rough if then statement listed above. I'll get more and update. Thanks. – Kwixotic Feb 22 '17 at 20:03

1 Answers1

0

1) Find the elements you'd like to update by using the SelectNodes function with the appropriate XPath statement.

'//*[(./@tag1=''A'' or ./@tag1=''D'') and ./@tag2 = ''B'']'

The above code says find any element which has an attribute tag1 with values 'A' or 'D' and also has an attribute tag2 with value 'B'.

2) For each element found by that above, assign that element's tag3 attribute with the value of its tag4 attribute.

| %{ #%{ is an alias (i.e. shorthand) for `| foreach-object`
    $_.tag3 = $_.tag4
}

Full Solution (with sample data)

$xml = [xml]@"
<xml>
<something tag1="A" tag2="B" tag3="0.00" tag4="2.00" />
<something tag1="C" tag2="B" tag3="0.00" tag4="2.00" />
<something tag1="D" tag2="B" tag3="0.00" tag4="2.00" />
</xml>
"@
$xml.SelectNodes('//*[(./@tag1=''A'' or ./@tag1=''D'') and ./@tag2 = ''B'']') | %{
    $_.tag3 = $_.tag4
}


##Demo Output (function from https://blogs.msdn.microsoft.com/powershell/2008/01/18/format-xml/)
function Format-XML ([xml]$xml, $indent=2) 
{ 
    $StringWriter = New-Object System.IO.StringWriter 
    $XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter 
    $xmlWriter.Formatting = 'indented'
    $xmlWriter.Indentation = $Indent 
    $xml.WriteContentTo($XmlWriter) 
    $XmlWriter.Flush() 
    $StringWriter.Flush() 
    Write-Output $StringWriter.ToString() 
}
Format-XML $xml

Update

I also noted that you mentioned reading the XML from file and saving it back to file... whilst in the above I'd just assigned a value to the $xml variable directly, and showed the output on screen.

To read XML from file, use $xml = [raw](get-content 'c:\path\to\file.xml' -raw). More info (in fact, with a slightly different approach) here:

To save XML back to file, just use $xml.Save('c:\path\to\file.xml')

Again, more info and alternate approaches here:

Community
  • 1
  • 1
JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
  • Thanks so much. I'm still learning so looking at the code relative to what I want it to do is the best way for me to see what each part is doing. I'll give this a shot, thanks for your time. – Kwixotic Feb 22 '17 at 20:07
  • No worries. I spotted in the comments above that you mention regex. NB: Whilst there are some scenarios where you have to use regex (e.g. if dealing with malformed XML) generally it's best to use XPath; a technology/language specifically designed for that scenario. A good starter is https://www.w3schools.com/xml/xpath_intro.asp. For PowerShell I learnt through https://www.goodreads.com/book/show/15815165-learn-windows-powershell-3-in-a-month-of-lunches & highly recommend it to others... though there are many other sources available. https://www.slant.co/improve/topics/1060/ – JohnLBevan Feb 22 '17 at 20:14