forked from brianary/scripts
-
Notifications
You must be signed in to change notification settings - Fork 14
/
ConvertFrom-XmlElement.ps1
105 lines (98 loc) · 3.36 KB
/
ConvertFrom-XmlElement.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<#
.SYNOPSIS
Converts named nodes of an element to properties of a PSObject, recursively.
.INPUTS
System.Xml.XmlElement to convert into a PSObject, or
System.Xml.XmlDocument to convert the document element into a PSObject, or
Microsoft.PowerShell.Commands.SelectXmlInfo output from Select-Xml to convert
each selected node into a PSObject.
.OUTPUTS
System.Management.Automation.PSCustomObject object created from selected XML.
.FUNCTIONALITY
XML
.LINK
Select-Xml
.EXAMPLE
Select-Xml /configuration/appSettings/add web.config |ConvertFrom-XmlElement.ps1
key value
--- -----
webPages:Enabled false
#>
#Requires -Version 3
[CmdletBinding()][OutputType([psobject])] Param(
# The XML document to convert to a PSObject.
[Parameter(ParameterSetName='Document',Position=0,Mandatory=$true,ValueFromPipeline=$true)][Xml.XmlDocument] $Document,
# The XML element to convert to a PSObject.
[Parameter(ParameterSetName='Element',Position=0,Mandatory=$true,ValueFromPipeline=$true)][Xml.XmlElement] $Element,
# Output from the Select-Xml cmdlet.
[Parameter(ParameterSetName='SelectXmlInfo',Position=0,Mandatory=$true,ValueFromPipeline=$true)]
[Microsoft.PowerShell.Commands.SelectXmlInfo] $SelectXmlInfo,
# Only include attributes, ignore other child nodes.
[Alias('Attributes','Atts')][switch] $OnlyAttributes
)
Process
{
switch($PSCmdlet.ParameterSetName)
{
Document {$Document.DocumentElement |ConvertFrom-XmlElement.ps1 -OnlyAttributes:$OnlyAttributes}
SelectXmlInfo
{
@($SelectXmlInfo |ForEach-Object {[Xml.XmlElement]$_.Node} |
ConvertFrom-XmlElement.ps1 -OnlyAttributes:$OnlyAttributes)
}
Element
{
if($OnlyAttributes)
{
$properties = @{}
$Element.Attributes |ForEach-Object {[void]$properties.Add($_.Name,$_.Value)}
return [pscustomobject]$properties
}
elseif($Element.HasChildNodes -and !($Element.ChildNodes.NodeType |
Select-Object -Unique |
Where-Object {$_ -notin [Xml.XmlNodeType]::Text,[Xml.XmlNodeType]::CDATA}))
{
return $Element.InnerText
}
elseif(($Element.SelectNodes('*') |Group-Object Name |Measure-Object).Count -eq 1)
{
return @($Element.SelectNodes('*') |ConvertFrom-XmlElement.ps1)
}
else
{
$properties = @{}
$Element.Attributes |ForEach-Object {[void]$properties.Add($_.Name,$_.Value)}
foreach($node in $Element.ChildNodes |Where-Object {$_.Name -and $_.Name -ne '#whitespace'})
{
$subelements = $node.SelectNodes('*') |Group-Object Name
$value =
if($node.InnerText -and !$subelements)
{
$node.InnerText
}
elseif(($subelements |Measure-Object).Count -eq 1)
{
$subelement = $node.SelectSingleNode('*')
[pscustomobject]@{$subelement.Name=@($subelement |ConvertFrom-XmlElement.ps1)}
}
else
{
ConvertFrom-XmlElement.ps1 $node
}
if(!$properties.Contains($node.Name))
{ # new property
[void]$properties.Add($node.Name,$value)
}
else
{ # property name collision!
if($properties[$node.Name] -isnot [Collections.Generic.List[object]])
{ $properties[$node.Name] = ([Collections.Generic.List[object]]@($properties[$node.Name],$value)) }
else
{ $properties[$node.Name].Add($value) }
}
}
return [pscustomobject]$properties
}
}
}
}