2010-07-14 12 views
16

Nota: Estoy usando ConvertTo-XML y no puede utilizar Export-Clixml:Convertir XML a psobject

puedo crear un simple PSObjec t:

$a = New-Object PSObject -Property @{ 
    Name='New' 
    Server = $null 
    Database = $null 
    UserName = $null 
    Password = $null 
} 

luego convertirlo en XML usando ConvertTo-XML:

$b = $a | Convertto-XML -NoTypeInformation 

XML se ve así:

<?xml version="1.0"?> 
<Objects> 
    <Object> 
    <Property Name="Password" /> 
    <Property Name="Name">New</Property> 
    <Property Name="Server" /> 
    <Property Name="UserName" /> 
    <Property Name="Database" /> 
    </Object> 
</Objects> 

Tengo problemas para descifrar la notación de puntos o la consulta XPath para extraer los atributos/elementos y convertir $b de nuevo en el PSObject original.

Respuesta

13

Puede hacerlo fácilmente con XPath. Aunque PowerShell generalmente hace que trabajar con XML sea bastante simple, en este caso creo que el formato que usa estrictamente la sintaxis de PowerShell sería bastante asqueroso.

filter XmlProperty([String]$Property) { 
    $_.SelectSingleNode("/Objects/Object/Property[@Name='$Property']").InnerText 
} 

$Name = $b | Xmlproperty Name 
$Server = $b | XmlProperty Server 
# etc... 

EDIT: Para hacer esto de forma genérica para un documento XML que contiene uno o más elementos de objetos, puede hacer algo como esto:

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 
+0

Gracias Josh. Me gustaría convertir cualquier objeto PSObject, pero esto es suficiente para comenzar. Estoy haciendo esto porque PSObject no es compatible con la serialización de .NET. –

+0

Actualicé mi respuesta con una forma más general de volver a PSObject. Sin embargo, no es recursivo, así que tenlo en cuenta. – Josh

+0

¡Agradable! Gracias de nuevo. –

0

Mi variante con profundidad ilimitada.

Ver ejemplos.

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 
    } 
} 
0

lo general analizar XML a tablas hash, pero utilizando la función ConvertTo agarré de here Adapté la función de convertir a pscustom objetos

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; 
     } 
    } 
} 
Cuestiones relacionadas