Last active
November 13, 2020 11:11
-
-
Save Sarafian/69bbcd750ae7e5c8f0bf5b46d01dc027 to your computer and use it in GitHub Desktop.
XML to JSON (CODIT)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.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