Skip to content

Instantly share code, notes, and snippets.

@Sarafian
Last active November 13, 2020 11:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sarafian/69bbcd750ae7e5c8f0bf5b46d01dc027 to your computer and use it in GitHub Desktop.
Save Sarafian/69bbcd750ae7e5c8f0bf5b46d01dc027 to your computer and use it in GitHub Desktop.
XML to JSON (CODIT)
<#
.SYNOPSIS
Converts [xml] objects to memory object
.DESCRIPTION
Converts [xml] objects to memory object with some control over attribute values and property names
.PARAMETER AttributesGroupProperty
Name of property for values read from node attributes
.PARAMETER LowerCasePropertyNames
Convert all property names lower case
.EXAMPLE
[xml]$xml=@"
<Root>
<SingleNode Attribute1="A1Value">SMValue</SingleNode>
<ArrayNode Attribute1="A1Value">
<SingleNode Attribute1="A1Value">SNValue1</SingleNode>
<SingleNode Attribute1="A1Value">SNValue2</SingleNode>
</ArrayNode>
<SharedNode Shared="SharedValue1">
<Shared>SharedValue2</Shared>
<Shared>SharedValue3</Shared>
</SharedNode>
</Root>
"@
$psObject=& ConvertFrom-XML.ps1 -Node $xml -Depth 100
#region Demo structure from $psObject|ConvertTo-Json
{
"Root": {
"SingleNode": [
"SMValue",
"SNValue1",
"SNValue2"
],
"ArrayNode": {
"$": {
"Attribute1": "A1Value"
},
"SingleNode": [
"SNValue1",
"SNValue2"
]
},
"SharedNode": {
"$": {
"Shared": "SharedValue1"
},
"Shared": [
"SharedValue2",
"SharedValue3"
]
}
}
}
#endregion
.EXAMPLE
[xml]$xml=@"
<Root>
<SingleNode Attribute1="A1Value">SMValue</SingleNode>
<ArrayNode Attribute1="A1Value">
<SingleNode Attribute1="A1Value">SNValue1</SingleNode>
<SingleNode Attribute1="A1Value">SNValue2</SingleNode>
</ArrayNode>
<SharedNode Shared="SharedValue1">
<Shared>SharedValue2</Shared>
<Shared>SharedValue3</Shared>
</SharedNode>
</Root>
"@
$psObject=& ConvertFrom-XML.ps1 -Node $xml -AttributesGroupProperty "AttributesGroup" -LowerCasePropertyNames
#region Demo structure from $psObject|ConvertTo-Json -Depth 100
{
"root": {
"singlenode": [
"SMValue",
"SNValue1",
"SNValue2"
],
"arraynode": {
"AttributesGroup": {
"attribute1": "A1Value"
},
"singlenode": [
"SNValue1",
"SNValue2"
]
},
"sharednode": {
"AttributesGroup": {
"shared": "SharedValue1"
},
"shared": [
"SharedValue2",
"SharedValue3"
]
}
}
}
#endregion
#>
param(
[Parameter(Mandatory=$true)]
[System.Xml.XmlNode]
$Node,
[Parameter(Mandatory=$false)]
[string]$AttributesGroupProperty='$',
[Parameter(Mandatory=$false)]
[switch]$LowerCasePropertyNames=$false
)
$selfSplat=@{}+$PSBoundParameters
$selfSplat.Remove("Node")
$selfPath=$MyInvocation.MyCommand.Path
#region Extract value nodes
if(-not $Node.HasChildNodes)
{
return $Node.Value
}
elseif($Node.FirstChild -as [System.Xml.XmlText])
{
return $Node.FirstChild.Value
}
else {
}
#endregion
#region Extract composite nodes
# Hashes to use with New-Object
$attributeHash=@{}
$propertyHash=@{}
foreach($memberName in $Node|Get-Member -MemberType Property|Select-Object -ExpandProperty Name)
{
# The name of the property to use in the new objects
$newName=$memberName
# Convert names to lower case
if($LowerCasePropertyNames)
{
$newName=$newName.ToLower()
}
if($Node -as [System.Xml.XmlDocument])
{
# This is the [xml] variable that was loaded as [System.Xml.XmlDocument]
$memberNode=$Node.($memberName)
if($memberNode -as [System.Xml.XmlNode])
{
# Dismiss the version property and go directly to root node which should be the only of type [System.Xml.XmlNode]
$object=& $selfPath @selfSplat -Node $memberNode
$propertyHash.Add($newName,$object)
}
}
else
{
# Members can be both attributes and nodes
# Check if member is first an attribute
$attributeNode=$Node.GetAttributeNode($memberName)
if($null -ne $attributeNode)
{
$attributeHash.Add($newName,$attributeNode.Value)
}
# Get nodes from member
$elementNodes=$Node.GetElementsByTagName($memberName)
switch ($elementNodes.Count) {
0 {
# No nodes for this member
# It was an attribute
}
1 {
# There is only one node
$elementNode=$elementNodes[0]
$object=& $selfPath @selfSplat -Node $elementNodes[0]
$propertyHash.Add($newName,$object)
}
Default {
# Create an empty array in the hash
$propertyHash.Add($newName,@())
foreach($elementNode in $elementNodes)
{
$object=& $selfPath @selfSplat -Node $elementNode
$propertyHash[$newName]+=$object
}
}
}
}
}
#endregion
#region Build the object
# Group attributes within a new property ($AttributesGroupProperty)
if($attributeHash.Count -gt 0)
{
$attributeObject=New-Object -Type psobject -Property $attributeHash
$propertyHash.Add($AttributesGroupProperty, $attributeObject)
}
if($propertyHash.Count -gt 0)
{
New-Object -Type PSOBject -Property $propertyHash
}
else {
$null
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment