Convert XML to PSObject
Note: I'm using ConvertTo-XML
and cannot use Export-Clixml
:
I create a simple PSObjec
t:
$a = New-Object PSObject -Property @{
Name='New'
Server = $null
Database = $null
UserName = $null
Password = $null
}
I then convert it into XML using ConvertTo-XML
:
$b = $a | Convertto-XML -NoTypeInformation
The XML looks like this:
<?xml version="1.0"?>
<Objects>
<Object>
<Property Name="Password" />
<Property Name="Name">开发者_Python百科;New</Property>
<Property Name="Server" />
<Property Name="UserName" />
<Property Name="Database" />
</Object>
</Objects>
I'm having trouble figuring out the dot notation or XPath query to extract the attributes/elements and convert $b
back to the original PSObject
.
You can do this pretty easily with XPath. Although PowerShell usually makes working with XML pretty simple, in this case I think the format using strictly PowerShell syntax would be pretty gross.
filter XmlProperty([String]$Property) {
$_.SelectSingleNode("/Objects/Object/Property[@Name='$Property']").InnerText
}
$Name = $b | Xmlproperty Name
$Server = $b | XmlProperty Server
# etc...
EDIT: To generically do this for an XML document that contains one or more Object elements, you can do something like this:
function ConvertFrom-Xml($XML) {
foreach ($Object in @($XML.Objects.Object)) {
$PSObject = New-Object PSObject
foreach ($Property in @($Object.Property)) {
$PSObject | Add-Member NoteProperty $Property.Name $Property.InnerText
}
$PSObject
}
}
ConvertFrom-Xml $b
My variant with unlimited depth.
See examples.
function ConvertFrom-Xml {
<#
.SYNOPSIS
Converts XML object to PSObject representation for further ConvertTo-Json transformation
.EXAMPLE
# JSON->XML
$xml = ConvertTo-Xml (get-content 1.json | ConvertFrom-Json) -Depth 4 -NoTypeInformation -as String
.EXAMPLE
# XML->JSON
ConvertFrom-Xml ([xml]($xml)).Objects.Object | ConvertTo-Json
#>
param([System.Xml.XmlElement]$Object)
if (($Object -ne $null) -and ($Object.Property -ne $null)) {
$PSObject = New-Object PSObject
foreach ($Property in @($Object.Property)) {
if ($Property.Property.Name -like 'Property') {
$PSObject | Add-Member NoteProperty $Property.Name ($Property.Property | % {ConvertFrom-Xml $_})
} else {
if ($Property.'#text' -ne $null) {
$PSObject | Add-Member NoteProperty $Property.Name $Property.'#text'
} else {
if ($Property.Name -ne $null) {
$PSObject | Add-Member NoteProperty $Property.Name (ConvertFrom-Xml $Property)
}
}
}
}
$PSObject
}
}
I usually parse xml to hash tables but using the convertto function I grabbed from here I adapted the function to convert to pscustom objects
function xmlNodeToPsCustomObject ($node){
$hash = @{}
foreach($attribute in $node.attributes){
$hash.$($attribute.name) = $attribute.Value
}
$childNodesList = ($node.childnodes | ?{$_ -ne $null}).LocalName
foreach($childnode in ($node.childnodes | ?{$_ -ne $null})){
if(($childNodesList | ?{$_ -eq $childnode.LocalName}).count -gt 1){
if(!($hash.$($childnode.LocalName))){
$hash.$($childnode.LocalName) += @()
}
if ($childnode.'#text' -ne $null) {
$hash.$($childnode.LocalName) += $childnode.'#text'
}
$hash.$($childnode.LocalName) += xmlNodeToPsCustomObject($childnode)
}else{
if ($childnode.'#text' -ne $null) {
$hash.$($childnode.LocalName) = $childnode.'#text'
}else{
$hash.$($childnode.LocalName) = xmlNodeToPsCustomObject($childnode)
}
}
}
return $hash | ConvertTo-PsCustomObjectFromHashtable
}
function ConvertTo-PsCustomObjectFromHashtable {
param (
[Parameter(
Position = 0,
Mandatory = $true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)] [object[]]$hashtable
);
begin { $i = 0; }
process {
foreach ($myHashtable in $hashtable) {
if ($myHashtable.GetType().Name -eq 'hashtable') {
$output = New-Object -TypeName PsObject;
Add-Member -InputObject $output -MemberType ScriptMethod -Name AddNote -Value {
Add-Member -InputObject $this -MemberType NoteProperty -Name $args[0] -Value $args[1];
};
$myHashtable.Keys | Sort-Object | % {
$output.AddNote($_, $myHashtable.$_);
}
$output
} else {
Write-Warning "Index $i is not of type [hashtable]";
}
$i += 1;
}
}
}
精彩评论