XmlSerializer functionality in PowerShell?

Is there a way to use the functionality of the .NET XmlSerializer class in PowerShell?

More specifically, the ability to easily output / serialize .NET types in Xml, for example.

XmlSerializer s = new XmlSerializer(typeof(MyType)); TextReader r = new StreamReader("sample.xml"); MyType myType = (MyType)s.Deserialize(r); r.Close(); 

I know I can call above from PowerShell, but is there a way to avoid defining MyType in a separate assembly? Thanks

[Edit] Since it seems that .NET type types cannot be added from PowerShell, let me redirect my question: is there an easy way, like XmlSerializer, to serialize types in PowerShell? I have to read / write some .xml from PS and rather use such functions before doing this manually.

+7
powershell xmlserializer
source share
1 answer

Of course, you can define the type inside Powershell and use it in serialization.

The first step is to define a new type. In Powershell 2.0, you can do this by calling Add-Type . When you have a dynamically compiled assembly containing a new type, you are free to use this type, like any other .NET type.

Step 2 is to simply use the XmlSerializer class, as usual - just translate the C # code provided in the question into Powershell.

The following example illustrates. It defines a simple type, then deserializes from an XML string to create a new instance of this type. He then prints the property values ​​on this de-serialized instance.

 $source1 = @" using System; using System.Xml; using System.Xml.Serialization; namespace MyDynamicTypes { [XmlRoot] public class Foo { [XmlElement] public string Message { get; set; } [XmlAttribute] public int Flavor { get; set; } } } "@ Add-Type -TypeDefinition $source1 -Language "CSharpVersion3" -ReferencedAssemblies System.Xml.dll $xml1 = @" <Foo Flavor='19'> <Message>Ephesians 5:11</Message> </Foo> "@ $f1 = New-Object MyDynamicTypes.Foo $sr = New-Object System.IO.StringReader($xml1) $s1 = New-Object System.Xml.Serialization.XmlSerializer( $f1.GetType() ) $xtr = New-Object System.Xml.XmlTextReader($sr) $foo = $s1.Deserialize($xtr) Write-Output ("foo.Flavor = " + $foo.Flavor) Write-Output ("foo.Message = " + $foo.Message) 

Thanks to Keith Hill for specifying Add-Type Add-Ins.


In Powershell 1.0, you can do something similar with some special code (see Powershell: compiling C # code stored in a string ).

 function Compile-Code { param ( [string[]] $code = $(throw "The parameter -code is required.") , [string[]] $references = @() , [switch] $asString = $false , [switch] $showOutput = $false , [switch] $csharp = $true , [switch] $vb = $false ) $options = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"; $options.Add( "CompilerVersion", "v3.5") if ( $vb ) { $provider = New-Object Microsoft.VisualBasic.VBCodeProvider $options } else { $provider = New-Object Microsoft.CSharp.CSharpCodeProvider $options } $parameters = New-Object System.CodeDom.Compiler.CompilerParameters @( "mscorlib.dll", "System.dll", "System.Core.dll", "System.Xml.dll", ([System.Reflection.Assembly]::GetAssembly( [PSObject] ).Location) ) + $references | Sort -unique |% { $parameters.ReferencedAssemblies.Add( $_ ) } | Out-Null $parameters.GenerateExecutable = $false $parameters.GenerateInMemory = !$asString $parameters.CompilerOptions = "/optimize" if ( $asString ) { $parameters.OutputAssembly = [System.IO.Path]::GetTempFileName() } $results = $provider.CompileAssemblyFromSource( $parameters, $code ) if ( $results.Errors.Count -gt 0 ) { if ( $output ) { $results.Output |% { Write-Output $_ } } else { $results.Errors |% { Write-Error $_.ToString() } } } else { if ( $asString ) { $content = [System.IO.File]::ReadAllBytes( $parameters.OutputAssembly ) $content = [Convert]::ToBase64String( $content ) [System.IO.File]::Delete( $parameters.OutputAssembly ); return $content } else { return $results.CompiledAssembly } } } 

With this function, the application becomes:

 $source1 = @" using System; using System.Xml; using System.Xml.Serialization; namespace MyDynamicTypes { [XmlRoot] public class Foo { [XmlElement] public string Message { get; set; } [XmlAttribute] public int Flavor { get; set; } } } "@ Compile-Code -csharp -code $source1 $xml1 = @" <Foo Flavor='19'> <Message>Ephesians 5:11</Message> </Foo> "@ $f1 = New-Object MyDynamicTypes.Foo $sr = New-Object System.IO.StringReader($xml1) $s1 = New-Object System.Xml.Serialization.XmlSerializer( $f1.GetType() ) $xtr = New-Object System.Xml.XmlTextReader($sr) $foo = $s1.Deserialize($xtr) Write-Output ("foo.Flavor = " + $foo.Flavor) Write-Output ("foo.Message = " + $foo.Message) 
+9
source share

All Articles