Grouping and totaling a sub-element of repeating elements in XML

Bernard Vander Beken

How can I group and sum the input XML so duplicate Item elements are merged?

  • All Item elements with the same ItemType,ItemID,Color combination need to be merged into 1 output element.
  • The MinQty element (integer value) needs to be the total of all input values.

Sample input XML

<Inventory>
  <Item>
    <ItemType>P</ItemType>
    <ItemID>37494</ItemID>
    <Color>11</Color>
    <MinQty>1</MinQty>
  </Item>
  <Item>
    <ItemType>P</ItemType>
    <ItemID>50254</ItemID>
    <Color>11</Color>
    <MinQty>4</MinQty>
  </Item>
  <Item>
    <ItemType>P</ItemType>
    <ItemID>37494</ItemID>
    <Color>11</Color>
    <MinQty>2</MinQty>
  </Item>
</Inventory>

Expected output XML

<Inventory>
  <Item>
    <ItemType>P</ItemType>
    <ItemID>37494</ItemID>
    <Color>11</Color>
    <MinQty>3</MinQty>
  </Item>
  <Item>
    <ItemType>P</ItemType>
    <ItemID>50254</ItemID>
    <Color>11</Color>
    <MinQty>4</MinQty>
  </Item>
</Inventory>

Current idea is based on this answer, using Group-Object. However I don't see how to combine this with the summing of a sub-element. Remove Duplicate XML Node Groups in Powershell

mklement0

A Group-Object solution that modifies the XML document in place:

# Parse the XML file into a DOM.
# Replace "sample.xml" with your XML file path.
($xmlDoc = [xml]::new()).Load((Convert-Path sample.xml))

# Loop over all <Item> elements.
$xmlDoc.Inventory.Item | 
  Group-Object ItemType, ItemId, Color | 
  Where-Object Count -gt 1 | 
  ForEach-Object {
    # Sum up all MinQty values and assign the sum to the first element
    # in the group.
    $_.Group[0].MinQty = [string] ($_.Group.MinQty | Measure-Object -Sum).Sum
    # Now remove all other elements in the group.
    $null = $_.Group[1..($_.Count-1)].ForEach({ $_.ParentNode.RemoveChild($_) })
  }

Note:

  • Casting the .Sum value to [string] explicitly is only required in Windows PowerShell, where only an actual string ([string] instance) is accepted on assignment to an XML element.
    PowerShell (Core) 7+, more conveniently performs stringification on demand.

  • A simple example:

     # OK in PS 7+: integer 2 is automatically converted to string.
     # In WinPS, you get the following error:
     #   Cannot set "el" because only strings can be used as 
     #   values to set XmlNode properties.'
     ($x = [xml] '<el>1</el>').el = 2 
    
     # Required in Windows PowerShell: RHS must be an actual string.
     ($x = [xml] '<el>1</el>').el = [string] 2 # simple alternative here: '2' 
    

Printing the XML text of the updated DOM, as shown below, matches the expected result in your question:

if ($IsCoreCLR) { # PowerShell (Core) 7+
  # Pretty-print
  ([System.Xml.Linq.XDocument] $xmlDoc.OuterXml).ToString()
} else { # Windows PowerShell 
  # No pretty-printing easily available, just print .OuterXml
  $xmlDoc.OuterXml
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Grouping XML elements in Swift

Deserialize XML with repeating (but different) elements

handling repeating xml elements in mule

totaling one column with repeating values from others

Querying and totaling certian elements in a list

Karate: Match repeating element in xml

Grouping values under elements FOR XML

How to open all xml sub-elements belonging to a certain element in a pandas dataframe, with each sub-element in a row

ListView element's sub element is repeating after a certain position

How to get all xml sub elements from a dom Element with loop in Java?

How to remove elements from a xml file based on the value of a sub element using ansible?

XSD - XML element must contain exactly 1 of 2 possible sub elements

Sub arraylist output repeating itself after n elements

Sum of elements based on grouping an element using scala?

Repeating XML element is not working in Internet Explorer

how reduce repeating element xml using xslt

Grouping & counting by two XML elements with XSLT

Grouping the elements inside the XML based on Attribute value

Grouping same xml elements using XSLT 2

Grouping XML multiple elements into a single one

How to match sub-level elements for grouping without dropping siblings?

json / jq : multi-level grouping of sub-elements in an array

How to include all the sub-elements of a sub-element in xslt?

Oracle XML Parse to Table Multiple Sub Elements

How to replace XML with sub-elements

Powershell script to add XML sub-elements

Powershell script to remove an XML sub-elements

Iterating over 2 elements in a list but repeating the second element in the next iteration

How to deepcopy a xml sub element in Python