PoshCode Logo PowerShell Code Repository

Xml Module 6.6 by Jaykul 18 months ago (modification of post by Joel Bennett view diff)
diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/3926"></script>download | new post

A complete set of XML functionality (especially if you don’t have PSCX), including reading and writing xml files (import-xml, export-xml), selecting (via xpath), updating, transforming and creating new xml documents.

In particular:

A DSL for creating XML documents.

Convert-Xml which supports parameters so you can use XSLT which require parameters

Select-XML which leverages Remove-XmlNamespace to simplify simple xml queries by allowing you to leave out the namespaces. It is important to note that this means that the returned results will not have namespaces in them, even if the input XML did.

ALSO NOTE: only raw XmlNodes are returned from Select-Xml, so the output isn’t compatible with the built in Select-Xml — instead, it’s equivalent to using it the way I usually do: Select-Xml ... | Select-Object -Expand Node

Update-Xml which allows you to append, insert, remove, and replace values in XML Documents

Remove-XmlElement which can remove nodes or attributes by namespace to clean-up designer-generated XML

In this Version: I exposed Convert-Xml for XSL stylesheets, and fixed a bug

  1. #requires -version 2.0
  2.  
  3. # Improves over the built-in Select-XML by leveraging Remove-XmlNamespace http`://poshcode.org/1492
  4. # to provide a -RemoveNamespace parameter -- if it's supplied, all of the namespace declarations
  5. # and prefixes are removed from all XML nodes (by an XSL transform) before searching.
  6. # IMPORTANT: returned results *will not* have namespaces in them, even if the input XML did.
  7.  
  8. # Also, only raw XmlNodes are returned from this function, so the output isn't completely compatible
  9. # with the built in Select-Xml. It's equivalent to using Select-Xml ... | Select-Object -Expand Node
  10.  
  11. # Version History:
  12. # Select-Xml 2.0 This was the first script version I wrote.
  13. #                it didn't function identically to the built-in Select-Xml with regards to parameter parsing
  14. # Select-Xml 2.1 Matched the built-in Select-Xml parameter sets, it's now a drop-in replacement
  15. #                BUT only if you were using the original with: Select-Xml ... | Select-Object -Expand Node
  16. # Select-Xml 2.2 Fixes a bug in the -Content parameterset where -RemoveNamespace was *presumed*
  17. # Version    3.0 Added New-XDocument and associated generation functions for my XML DSL
  18. # Version    3.1 Fixed a really ugly bug in New-XDocument in 3.0 which I should not have released
  19. # Version    4.0 Never content to leave well enough alone, I've completely reworked New-XDocument
  20. # Version    4.1 Tweaked namespaces again so they don't cascade down when they shouldn't. Got rid of the unnecessary stack.
  21. # Version    4.2 Tightened xml: only cmdlet, function, and external scripts, with "-" in their names are exempted from being converted into xml tags.
  22. #                Fixed some alias error messages caused when PSCX is already loaded (we overwrite their aliases for cvxml and fxml)
  23. # Version    4.3 Added a Path parameter set to Format-Xml so you can specify xml files for prety printing
  24. # Version    4.5 Fixed possible [Array]::Reverse call on a non-array in New-XElement (used by New-XDocument)
  25. #                Work around possible variable slipping on null values by:
  26. #                1) allowing -param:$value syntax (which doesn't fail when $value is null)
  27. #                2) testing for -name syntax on the value and using it as an attribute instead
  28. # Version    4.6 Added -Arguments to Convert-Xml so that you can pass arguments to XSLT transforms!
  29. #                Note: when using strings for xslt, make sure you single quote them or escape the $ signs.
  30. # Version    4.7 Fixed a typo in the namespace parameter of Select-Xml
  31. # Version    4.8 Fixed up some uses of Select-Xml -RemoveNamespace
  32. # Version    5.0 Added Update-Xml to allow setting xml attributes or node content
  33. # Version    6.0 Major cleanup, breaking changes.
  34. #       - Added Get-XmlContent and Set-XmlContent for loading/saving XML from files or strings
  35. #       - Removed Path and Content parameters from the other functions (it greatly simplifies thost functions, and makes the whole thing more maintainable)
  36. #       - Updated Update-Xml to support adding nodes "before" and "after" other nodes, and to support "remove"ing nodes
  37. # Version    6.1 Update for PowerShell 3.0
  38. # Version    6.2 Minor tweak in exception handling for CliXml
  39. # Version    6.3 Added Remove-XmlElement to allow removing nodes or attributes
  40. #                This is something I specifically needed to remove "ignorable" namespaces
  41. #                Specifically, the ones created by the Visual Studio Workflow designer (and perhaps other visual designers like Blend)
  42. #                Which I don't want to check into source control, because it makes diffing nearly impossible
  43. # Version    6.4 Fixed a bug on New-XElement for Rudy Shockaert (nice bug report, thanks!)
  44. # Version    6.5 Added -Parameters @{} parameter to New-XDocument to allow local variables to be passed into the module scope. *grumble*
  45. # Version    6.6 Expose Convert-Xml and fix a couple of bugs (I can't figure how they got here)
  46.  
  47. function Add-Accelerator {
  48. <#
  49.    .Synopsis
  50.       Add a type accelerator to the current session
  51.    .Description
  52.       The Add-Accelerator function allows you to add a simple type accelerator (like [regex]) for a longer type (like [System.Text.RegularExpressions.Regex]).
  53.    .Example
  54.       Add-Accelerator list System.Collections.Generic.List``1
  55.       $list = New-Object list[string]
  56.      
  57.       Creates an accelerator for the generic List[T] collection type, and then creates a list of strings.
  58.    .Example
  59.       Add-Accelerator "List T", "GList" System.Collections.Generic.List``1
  60.       $list = New-Object "list t[string]"
  61.      
  62.       Creates two accelerators for the Generic List[T] collection type.
  63.    .Parameter Accelerator
  64.       The short form accelerator should be just the name you want to use (without square brackets).
  65.    .Parameter Type
  66.       The type you want the accelerator to accelerate (without square brackets)
  67.    .Notes
  68.       When specifying multiple values for a parameter, use commas to separate the values.
  69.       For example, "-Accelerator string, regex".
  70.      
  71.       PowerShell requires arguments that are "types" to NOT have the square bracket type notation, because of the way the parsing engine works.  You can either just type in the type as System.Int64, or you can put parentheses around it to help the parser out: ([System.Int64])
  72.  
  73.       Also see the help for Get-Accelerator and Remove-Accelerator
  74.    .Link
  75.       http://huddledmasses.org/powershell-2-ctp3-custom-accelerators-finally/
  76. #>
  77. [CmdletBinding()]
  78. param(
  79.    [Parameter(Position=0,ValueFromPipelineByPropertyName=$true)]
  80.    [Alias("Key","Name")]
  81.    [string[]]$Accelerator
  82. ,
  83.    [Parameter(Position=1,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  84.    [Alias("Value","FullName")]
  85.    [type]$Type
  86. )
  87. process {
  88.    # add a user-defined accelerator  
  89.    foreach($a in $Accelerator) {
  90.       if($xlr8r::AddReplace) {
  91.          $xlr8r::AddReplace( $a, $Type)
  92.       } else {
  93.          $null = $xlr8r::Remove( $a )
  94.          $xlr8r::Add( $a, $Type)
  95.       }
  96.       trap [System.Management.Automation.MethodInvocationException] {
  97.          if($xlr8r::get.keys -contains $a) {
  98.             if($xlr8r::get[$a] -ne $Type) {
  99.                Write-Error "Cannot add accelerator [$a] for [$($Type.FullName)]`n                  [$a] is already defined as [$($xlr8r::get[$a].FullName)]"
  100.             }
  101.             Continue;
  102.          }
  103.          throw
  104.       }
  105.    }
  106. }
  107. }
  108.  
  109. &{
  110. $local:xlr8r = [psobject].assembly.gettype("System.Management.Automation.TypeAccelerators")
  111. $local:xlinq = [Reflection.Assembly]::Load("System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
  112. $xlinq.GetTypes() | ? { $_.IsPublic -and !$_.IsSerializable -and $_.Name -ne "Extensions" -and !$xlr8r::Get[$_.Name] } | Add-Accelerator
  113.  
  114. Add-Accelerator "Dictionary" "System.Collections.Generic.Dictionary``2, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  115. Add-Accelerator "PSParser" "System.Management.Automation.PSParser, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  116. }
  117.  
  118.  
  119. function Get-XmlContent {
  120. #.Synopsis
  121. #   Load an XML file as an XmlDocument
  122. param(
  123.     # Specifies a string that contains the XML to load, or a path to a file which has the XML to load (wildcards are permitted).
  124.     [Parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  125.     [ValidateNotNullOrEmpty()]
  126.     [Alias("PSPath","Path")]
  127.     [String[]]$Content
  128. ,
  129.     # If set, loads XML with all namespace qualifiers removed, and all entities expanded.
  130.     [Alias("Rn","Rm")]
  131.     [Switch]$RemoveNamespace
  132. )
  133. begin {
  134.     [Text.StringBuilder]$XmlContent = [String]::Empty
  135.     [bool]$Path = $true
  136. }
  137. process {
  138.     if($Path -and ($Path = Test-Path @($Content)[0] -EA 0)) {
  139.         foreach($file in Resolve-Path $Content) {
  140.             $xml = New-Object System.Xml.XmlDocument;
  141.             if($file.Provider.Name -eq "FileSystem") {
  142.                 Write-Verbose $file.ProviderPath
  143.                 $xml.Load( $file.ProviderPath )
  144.             } else {
  145.                 $ofs = "`n"
  146.                 $xml.LoadXml( ([String](Get-Content $file)) )
  147.             }
  148.         }
  149.         if($RemoveNamespace) {
  150.             $xml.LoadXml( (Remove-XmlNamespace -Xml $xml.DocumentElement) )
  151.         }
  152.         Write-Output $xml
  153.  
  154.     } else {
  155.         # If the "path" parameter isn't actually a path, assume that it's actually content
  156.         foreach($line in $content) {
  157.             $null = $XmlContent.AppendLine( $line )
  158.         }
  159.     }
  160. }
  161. end {
  162.     if(!$Path) {
  163.         $xml = New-Object System.Xml.XmlDocument;
  164.         $xml.LoadXml( $XmlContent.ToString() )
  165.         if($RemoveNamespace) {
  166.             $xml.LoadXml( (Remove-XmlNamespace -Xml $xml.DocumentElement) )
  167.         }
  168.         Write-Output $xml
  169.     }
  170.  
  171. }}
  172.  
  173.  
  174. Set-Alias Import-Xml Get-XmlContent
  175. Set-Alias ipxml Get-XmlContent
  176. Set-Alias ipx Get-XmlContent
  177. Set-Alias Get-Xml Get-XmlContent
  178. Set-Alias gxml Get-XmlContent
  179. Set-Alias gx Get-XmlContent
  180.  
  181. function Set-XmlContent {
  182. param(
  183.     [Parameter(Mandatory=$true, Position=1)]
  184.     [Alias("PSPath")]
  185.     [String]$Path
  186. ,
  187.     # Specifies one or more XML nodes to search.
  188.     [Parameter(Position=5,ParameterSetName="Xml",Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  189.     [ValidateNotNullOrEmpty()]
  190.     [Alias("Node")]
  191.     [Xml]$Xml
  192. )
  193. process {
  194.     $xml.Save( $Path )
  195. }
  196. }
  197.  
  198. Set-Alias Export-Xml Set-XmlContent
  199. Set-Alias epxml Set-XmlContent
  200. Set-Alias epx Set-XmlContent
  201. Set-Alias Set-Xml Set-XmlContent
  202. Set-Alias sxml Set-XmlContent
  203. Set-Alias sx Set-XmlContent
  204.  
  205. function Format-Xml {
  206. #.Synopsis
  207. #   Pretty-print formatted XML source
  208. #.Description
  209. #   Runs an XmlDocument through an auto-indenting XmlWriter
  210. #.Parameter Xml
  211. #   The Xml Document
  212. #.Parameter Path
  213. #   The path to an xml document (on disc or any other content provider).
  214. #.Parameter Indent
  215. #   The indent level (defaults to 2 spaces)
  216. #.Example
  217. #   [xml]$xml = get-content Data.xml
  218. #   C:\PS>Format-Xml $xml
  219. #.Example
  220. #   get-content Data.xml | Format-Xml
  221. #.Example
  222. #   Format-Xml C:\PS\Data.xml
  223. #.Example
  224. #   ls *.xml | Format-Xml
  225. #
  226. [CmdletBinding()]
  227. param(
  228.    [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="Document")]
  229.    [xml]$Xml
  230. ,
  231.    [Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="File")]
  232.    [Alias("PsPath")]
  233.    [string]$Path
  234. ,
  235.    [Parameter(Mandatory=$false)]
  236.    $Indent=2
  237. )
  238. process {
  239.    ## Load from file, if necessary
  240.    if($Path) { [xml]$xml = Get-Content $Path }
  241.    
  242.    $StringWriter = New-Object System.IO.StringWriter
  243.    $XmlWriter = New-Object System.Xml.XmlTextWriter $StringWriter
  244.    $xmlWriter.Formatting = "indented"
  245.    $xmlWriter.Indentation = $Indent
  246.    $xml.WriteContentTo($XmlWriter)
  247.    $XmlWriter.Flush()
  248.    $StringWriter.Flush()
  249.    Write-Output $StringWriter.ToString()
  250. }}
  251. Set-Alias fxml Format-Xml -EA 0
  252. Set-Alias fx   Format-Xml -EA 0
  253.  
  254. function Select-XmlNodeInternal {
  255. [CmdletBinding()]
  256. param([Xml.XmlNode[]]$Xml, [String[]]$XPath, [Hashtable]$NamespaceManager)
  257. begin {
  258.     Write-Verbose "XPath = $($XPath -join ',')"
  259.     foreach($node in $xml) {
  260.         if($NamespaceManager) {
  261.             $nsManager = new-object System.Xml.XmlNamespaceManager $node.NameTable
  262.             foreach($ns in $NamespaceManager.GetEnumerator()) {
  263.                 $nsManager.AddNamespace( $ns.Key, $ns.Value )
  264.             }
  265.             Write-Verbose "Names = $($nsManager | % { @{ $_ = $nsManager.LookupNamespace($_) } } | Out-String)"
  266.         }
  267.         foreach($path in $xpath) {
  268.             $node.SelectNodes($path, $nsManager)
  269.         }
  270.     }
  271. }}
  272.  
  273. function Select-Xml {
  274. #.Synopsis
  275. #  The Select-XML cmdlet lets you use XPath queries to search for text in XML strings and documents. Enter an XPath query, and use the Content, Path, or Xml parameter to specify the XML to be searched.
  276. #.Description
  277. #  Improves over the built-in Select-XML by leveraging Remove-XmlNamespace to provide a -RemoveNamespace parameter -- if it's supplied, all of the namespace declarations and prefixes are removed from all XML nodes (by an XSL transform) before searching.  
  278. #  
  279. #  However, only raw XmlNodes are returned from this function, so the output isn't currently compatible with the built in Select-Xml, but is equivalent to using Select-Xml ... | Select-Object -Expand Node
  280. #
  281. #  Also note that if the -RemoveNamespace switch is supplied the returned results *will not* have namespaces in them, even if the input XML did, and entities get expanded automatically.
  282. [CmdletBinding(DefaultParameterSetName="Xml")]
  283. param(
  284.     # Specifies an XPath search query. The query language is case-sensitive. This parameter is required.
  285.     [Parameter(Position=1,Mandatory=$true,ValueFromPipeline=$false)]
  286.     [ValidateNotNullOrEmpty()]
  287.     [Alias("Query")]
  288.     [String[]]$XPath
  289. ,
  290.     # Specifies a string that contains the XML to search. You can also pipe strings to Select-XML.
  291.     [Parameter(ParameterSetName="Content",Mandatory=$true)]
  292.     [ValidateNotNullOrEmpty()]
  293.     [String[]]$Content
  294. ,
  295.     # Specifies the path and file names of the XML files to search.  Wildcards are permitted.
  296.     [Parameter(Position=5,ParameterSetName="Path",Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
  297.     [ValidateNotNullOrEmpty()]
  298.     [Alias("PSPath")]
  299.     [String[]]$Path
  300. ,
  301.     # Specifies one or more XML nodes to search.
  302.     [Parameter(Position=5,ParameterSetName="Xml",Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  303.     [ValidateNotNullOrEmpty()]
  304.     [Alias("Node")]
  305.     [System.Xml.XmlNode[]]$Xml
  306. ,
  307.     # Specifies a hash table of the namespaces used in the XML. Use the format @{<namespaceName> = <namespaceUri>}.
  308.     [Parameter(Position=10,Mandatory=$false)]
  309.     [ValidateNotNullOrEmpty()]
  310.     [Alias("Ns")]
  311.     [Hashtable]$Namespace
  312. ,
  313.     # Allows the execution of XPath queries without namespace qualifiers.
  314.     #
  315.     # If you specify the -RemoveNamespace switch, all namespace declarations and prefixes are actually removed from the Xml before the XPath search query is evaluated, and your XPath query should therefore NOT contain any namespace prefixes.
  316.     #
  317.     # Note that this means that the returned results *will not* have namespaces in them, even if the input XML did, and entities get expanded automatically.
  318.     [Alias("Rn","Rm")]
  319.     [Switch]$RemoveNamespace
  320. )
  321. begin {
  322.     $NSM = $Null; if($PSBoundParameters.ContainsKey("Namespace")) { $NSM = $Namespace }
  323.     $XmlNodes = New-Object System.Xml.XmlNode[] 1
  324.     if($PSCmdlet.ParameterSetName -eq "Content") {
  325.         $XmlNodes = Get-XmlContent $Content -RemoveNamespace:$RemoveNamespace
  326.         Select-XmlNodeInternal $XmlNodes $XPath $NSM
  327.     }
  328. }
  329. process {
  330.     switch($PSCmdlet.ParameterSetName) {
  331.         "Path" {
  332.             $node = Get-XmlContent $Path -RemoveNamespace:$RemoveNamespace
  333.             Select-XmlNodeInternal $node $XPath $NSM
  334.         }
  335.         "Xml" {
  336.             foreach($node in $Xml) {
  337.                 if($RemoveNamespace) {
  338.                    [Xml]$node = Remove-XmlNamespace -Xml $node
  339.                 }
  340.                 Select-XmlNodeInternal $node $XPath $NSM
  341.             }
  342.         }
  343.     }
  344. }}
  345. Set-Alias slxml Select-Xml -EA 0
  346. Set-Alias slx Select-Xml -EA 0
  347.  
  348.  
  349. function Update-Xml {
  350. #.Synopsis
  351. #  The Update-XML cmdlet lets you use XPath queries to replace text in nodes in XML documents. Enter an XPath query, and use the Content, Path, or Xml parameter to specify the XML to be searched.
  352. #.Description
  353. #  Allows you to update an attribute value, xml node contents, etc.
  354. #
  355. #.Notes
  356. #  We still need to implement RemoveNode and RemoveAttribute and even ReplaceNode
  357. [CmdletBinding(DefaultParameterSetName="Set")]
  358. param(
  359.     # Specifies an XPath for an element where you want to insert the new node.
  360.     [Parameter(ParameterSetName="Before",Mandatory=$true)]
  361.     [ValidateNotNullOrEmpty()]
  362.     [Switch]$Before
  363. ,
  364.     # Specifies an XPath for an element where you want to insert the new node.
  365.     [Parameter(ParameterSetName="After",Mandatory=$true)]
  366.     [ValidateNotNullOrEmpty()]
  367.     [Switch]$After
  368. ,
  369.     # If set, the new value will be added as a new child of the node identified by the XPath
  370.     [Parameter(ParameterSetName="Append",Mandatory=$true)]
  371.     [Switch]$Append
  372. ,
  373.     # If set, the node identified by the XPath will be removed instead of set
  374.     [Parameter(ParameterSetName="Remove",Mandatory=$true)]
  375.     [Switch]$Remove
  376. ,
  377.     # If set, the node identified by the XPath will be Replace instead of set
  378.     [Parameter(ParameterSetName="Replace",Mandatory=$true)]
  379.     [Switch]$Replace
  380. ,
  381.     # Specifies an XPath for the node to update. This could be an element node *or* an attribute node (remember: //element/@attribute )
  382.     [Parameter(Position=1,Mandatory=$true)]
  383.     [ValidateNotNullOrEmpty()]
  384.     [String[]]$XPath
  385. ,
  386.     # The new value to place in the xml
  387.     [Parameter(Position=2,Mandatory=$true,ValueFromPipeline=$false)]
  388.     [ValidateNotNullOrEmpty()]
  389.     [String]$Value
  390. ,
  391.     # Specifies one or more XML nodes to search.
  392.     [Parameter(Position=5,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  393.     [ValidateNotNullOrEmpty()]
  394.     [Alias("Node")]
  395.     [System.Xml.XmlNode[]]$Xml
  396. ,  
  397.     # Specifies a hash table of the namespaces used in the XML. Use the format @{<namespaceName> = <namespaceUri>}.
  398.     [Parameter(Position=10,Mandatory=$false)]
  399.     [ValidateNotNullOrEmpty()]
  400.     [Alias("Ns")]
  401.     [Hashtable]$Namespace
  402. ,  
  403.     # Output the XML documents after adding updating them
  404.     [Switch]$Passthru
  405. )
  406. process
  407. {
  408.     foreach($XmlNode in $Xml) {
  409.         $select = @{}
  410.         $select.Xml = $XmlNode
  411.         $select.XPath = $XPath
  412.         if($Namespace) {  
  413.             $select.Namespace = $Namespace
  414.         }
  415.         $document =
  416.             if($XmlNode -is [System.Xml.XmlDocument]) {
  417.                 $XmlNode
  418.             } else {
  419.                 $XmlNode.get_OwnerDocument()
  420.             }
  421.         if($xValue = $Value -as [Xml]) {
  422.             $xValue = $document.ImportNode($xValue.SelectSingleNode("/*"), $true)
  423.         }
  424.         $nodes = Select-Xml @Select | Where-Object { $_ }
  425.  
  426.         if(@($nodes).Count -eq 0) { Write-Warning "No nodes matched your XPath, nothing will be updated" }
  427.        
  428.         foreach($node in $nodes) {
  429.             $select.XPath = "$XPath/parent::*"
  430.             $parent = Select-Xml @Select
  431.             if(!$xValue) {
  432.                 if($node -is [System.Xml.XmlAttribute] -and $Value.Contains("=")) {
  433.                     $aName, $aValue = $Value.Split("=",2)
  434.                     if($aName.Contains(":")){
  435.                         $ns,$name = $aName.Split(":",2)
  436.                         $xValue = $document.CreateAttribute( $name, $Namespace[$ns] )
  437.                     } else {
  438.                         $xValue = $document.CreateAttribute( $aName )
  439.                     }
  440.                     $xValue.Value = $aValue
  441.                 }
  442.             }
  443.            
  444.             switch($PSCmdlet.ParameterSetName) {
  445.                 "Before" {
  446.                     $null = $parent.InsertBefore( $xValue, $node )
  447.                 }
  448.                 "After" {
  449.                     $null = $parent.InsertAfter( $xValue, $node )
  450.                 }
  451.                 "Append" {
  452.                     $null = $parent.AppendChild( $xValue )
  453.                 }
  454.                 "Remove" {
  455.                     $null = $parent.RemoveChild( $node )
  456.                 }
  457.                 "Replace" {
  458.                     if(!$xValue) {
  459.                         $xValue = $document.CreateTextNode( $Value )
  460.                     }
  461.                     $null = $parent.ReplaceChild( $xValue, $node )
  462.                 }
  463.                 "Set" {
  464.                     if(!$xValue -and $node."#text") {
  465.                         $node."#text" = $Value
  466.                     } else {
  467.                         if($node -is [System.Xml.XmlElement]) {
  468.                             if(!$xValue) {
  469.                                 $xValue = $document.CreateTextNode( $Value )
  470.                             }
  471.                             $null = $node.set_innerXml("")
  472.                             $null = $node.AppendChild($xValue)
  473.                         }
  474.                         elseif($node -is [System.Xml.XmlAttribute]) {
  475.                             $node.Value = $Value
  476.                         } else {
  477.                             Write-Warning "$XPath selects a node of type $($node.GetType()), which we haven't handled. Please add that handler!"
  478.                         }
  479.                     }
  480.                 }
  481.             }
  482.         }
  483.         if($Passthru) {
  484.             Write-Output $XmlNode
  485.         }
  486.     }
  487. }}
  488. Set-Alias uxml Update-Xml -EA 0
  489. Set-Alias ux Update-Xml -EA 0
  490.  
  491. function Convert-Node {
  492. #.Synopsis
  493. # Convert a single XML Node via XSL stylesheets
  494. [CmdletBinding(DefaultParameterSetName="Reader")]
  495. param(
  496.    [Parameter(ParameterSetName="ByNode",Mandatory=$true,ValueFromPipeline=$true)]
  497.    [System.Xml.XmlNode]$Node
  498. ,
  499.    [Parameter(ParameterSetName="Reader",Mandatory=$true,ValueFromPipeline=$true)]
  500.    [System.Xml.XmlReader]$XmlReader
  501. ,
  502.    [Parameter(Position=1,Mandatory=$true,ValueFromPipeline=$false)]
  503.    [System.Xml.Xsl.XslCompiledTransform]$StyleSheet
  504. ,
  505.    [Parameter(Position=2,Mandatory=$false)]
  506.    [Alias("Parameters")]
  507.    [hashtable]$Arguments
  508. )
  509. PROCESS {
  510.    if($PSCmdlet.ParameterSetName -eq "ByNode") {
  511.       $XmlReader = New-Object Xml.XmlNodeReader $node
  512.    }
  513.  
  514.    $output = New-Object IO.StringWriter
  515.    $argList = $null
  516.    
  517.    if($Arguments) {
  518.       $argList = New-Object System.Xml.Xsl.XsltArgumentList
  519.       foreach($arg in $Arguments.GetEnumerator()) {
  520.          $namespace, $name = $arg.Key -split ":"
  521.          ## Fix namespace
  522.          if(!$name) {
  523.             $name = $Namespace
  524.             $namespace = ""
  525.          }
  526.          
  527.          Write-Verbose "ns:$namespace name:$name value:$($arg.Value)"
  528.          $argList.AddParam($name,"$namespace",$arg.Value)
  529.       }
  530.    }
  531.    
  532.    $StyleSheet.Transform( $XmlReader, $argList, $output )
  533.    Write-Output $output.ToString()
  534. }
  535. }
  536.  
  537. function Convert-Xml {
  538. #.Synopsis
  539. #   The Convert-XML function lets you use Xslt to transform XML strings and documents.
  540. #.Description
  541. #   Documentation TODO
  542. [CmdletBinding(DefaultParameterSetName="Xml")]
  543. param(
  544.     # Specifies one or more XML nodes to process.
  545.     [Parameter(Position=1,ParameterSetName="Xml",Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  546.     [ValidateNotNullOrEmpty()]
  547.     [Alias("Node")]
  548.     [System.Xml.XmlNode[]]$Xml
  549. ,  
  550.     # Specifies an Xml StyleSheet to transform with...
  551.     [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false)]
  552.     [ValidateNotNullOrEmpty()]
  553.     [Alias("StyleSheet")]
  554.     [String]$Xslt
  555. ,
  556.     # Specify arguments to the XSL Transformation
  557.     [Alias("Parameters")]
  558.     [hashtable]$Arguments
  559. )
  560. begin {
  561.    $StyleSheet = New-Object System.Xml.Xsl.XslCompiledTransform
  562.    if(Test-Path $Xslt -EA 0) {
  563.       Write-Verbose "Loading Stylesheet from $(Resolve-Path $Xslt)"
  564.       $StyleSheet.Load( (Resolve-Path $Xslt) )
  565.    } else {
  566.       $OFS = "`n"
  567.       Write-Verbose "$Xslt"
  568.       $StyleSheet.Load(([System.Xml.XmlReader]::Create((New-Object System.IO.StringReader $Xslt))))
  569.    }
  570. }
  571. process {
  572.    foreach($node in $Xml) {
  573.       Convert-Node -Xml (New-Object Xml.XmlNodeReader $node) $StyleSheet $Arguments
  574.    }
  575. }
  576. }
  577. Set-Alias cvxml Convert-Xml -EA 0
  578.  
  579. function Remove-XmlNamespace {
  580. #.Synopsis
  581. #  Removes namespace definitions and prefixes from xml documents
  582. #.Description
  583. #  Runs an xml document through an XSL Transformation to remove namespaces from it if they exist.
  584. #  Entities are also naturally expanded
  585. #.Parameter Content
  586. #  Specifies a string that contains the XML to transform.
  587. #.Parameter Path
  588. #  Specifies the path and file names of the XML files to transform. Wildcards are permitted.
  589. #
  590. #  There will be one output document for each matching input file.
  591. #.Parameter Xml
  592. #  Specifies one or more XML documents to transform
  593. [CmdletBinding(DefaultParameterSetName="Xml")]
  594. PARAM(
  595.    [Parameter(Position=1,ParameterSetName="Xml",Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  596.    [ValidateNotNullOrEmpty()]
  597.    [Alias("Node")]
  598.    [System.Xml.XmlNode[]]$Xml
  599. )
  600. BEGIN {
  601.    $StyleSheet = New-Object System.Xml.Xsl.XslCompiledTransform
  602.    $StyleSheet.Load(([System.Xml.XmlReader]::Create((New-Object System.IO.StringReader @"
  603. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  604.   <xsl:output method="xml" indent="yes"/>
  605.   <xsl:template match="/|comment()|processing-instruction()">
  606.      <xsl:copy>
  607.         <xsl:apply-templates/>
  608.      </xsl:copy>
  609.   </xsl:template>
  610.  
  611.   <xsl:template match="*">
  612.      <xsl:element name="{local-name()}">
  613.         <xsl:apply-templates select="@*|node()"/>
  614.      </xsl:element>
  615.   </xsl:template>
  616.  
  617.   <xsl:template match="@*">
  618.      <xsl:attribute name="{local-name()}">
  619.         <xsl:value-of select="."/>
  620.      </xsl:attribute>
  621.   </xsl:template>
  622. </xsl:stylesheet>
  623. "@))))
  624.    [Text.StringBuilder]$XmlContent = [String]::Empty
  625. }
  626. PROCESS {
  627.    $Xml | Convert-Node $StyleSheet
  628. }
  629. }
  630. Set-Alias rmns Remove-XmlNamespace -EA 0
  631. Set-Alias rmxns Remove-XmlNamespace -EA 0
  632.  
  633.  
  634.  
  635.  
  636.  
  637. function Remove-XmlElement {
  638. #.Synopsis
  639. #  Removes specified elements (tags or attributes) or all elements from a specified namespace from an Xml document
  640. #.Description
  641. #  Runs an xml document through an XSL Transformation to remove tag namespaces from it if they exist.
  642. #  Entities are also naturally expanded
  643. #.Parameter Content
  644. #  Specifies a string that contains the XML to transform.
  645. #.Parameter Path
  646. #  Specifies the path and file names of the XML files to transform. Wildcards are permitted.
  647. #
  648. #  There will be one output document for each matching input file.
  649. #.Parameter Xml
  650. #  Specifies one or more XML documents to transform
  651. [CmdletBinding(DefaultParameterSetName="Xml")]
  652. PARAM(
  653.    [Parameter(Position=0,ParameterSetName="Xml")] #,Mandatory=$true
  654.    #[ValidateNotNullOrEmpty()]
  655.    [XNamespace[]]$Namespace
  656. ,
  657.    [Parameter(Position=1,ParameterSetName="Xml",Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  658.    [ValidateNotNullOrEmpty()]
  659.    [Alias("Node")]
  660.    [System.Xml.XmlNode[]]$Xml
  661. )
  662. BEGIN {
  663.    foreach($Node in @($Xml)) {
  664.       $Allspaces += Get-Namespace -Xml $Node
  665.  
  666.       $nsManager = new-object System.Xml.XmlNamespaceManager $node.NameTable
  667.       foreach($ns in $Allspaces.GetEnumerator()) {
  668.           $nsManager.AddNamespace( $ns.Key, $ns.Value )
  669.       }
  670.  
  671.       # If no namespaces are passed in, use the "ignorable" ones from XAML if there are any
  672.       if(!$Namespace) {
  673.          $root = $Node.DocumentElement
  674.          # $nsManager = new-object System.Xml.XmlNamespaceManager $Node.NameTable                      
  675.          $nsManager.AddNamespace("compat", "http://schemas.openxmlformats.org/markup-compatibility/2006")
  676.          if($ignorable = $root.SelectSingleNode("@compat:Ignorable",$nsManager)) {
  677.             foreach($prefix in $ignorable.get_InnerText().Split(" ")) {
  678.                $Namespace += $root.GetNamespaceOfPrefix($prefix)
  679.             }
  680.          }
  681.       }
  682.    }
  683.  
  684.    
  685.    Write-Verbose "$Namespace"
  686.    $i = 0
  687.    $NSString = $(foreach($n in $Namespace) { "xmlns:n$i='$n'"; $i+=1 }) -Join " "
  688.    $EmptyTransforms = $(for($i =0; $i -lt $Namespace.Count;$i++) {
  689.       "<xsl:template match='n${i}:*'>
  690.      </xsl:template>
  691.      <xsl:template match='@n${i}:*'>
  692.      </xsl:template>"
  693.    })
  694.    
  695.    $XSLT = @"
  696. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" $NSString>
  697.   <xsl:output method="xml" indent="yes"/>
  698.   <xsl:template match="@*|node()">
  699.      <xsl:copy>
  700.         <xsl:apply-templates select="@*|node()"/>
  701.      </xsl:copy>
  702.   </xsl:template>
  703.   $EmptyTransforms
  704. </xsl:stylesheet>
  705. "@
  706.    Write-Verbose $XSLT
  707.  
  708.    $StyleSheet = New-Object System.Xml.Xsl.XslCompiledTransform
  709.    $StyleSheet.Load(([System.Xml.XmlReader]::Create((New-Object System.IO.StringReader $XSLT))))
  710.    [Text.StringBuilder]$XmlContent = [String]::Empty
  711. }
  712. PROCESS {
  713.    $Xml | Convert-Node $StyleSheet
  714. }
  715. }
  716. #Set-Alias rmns Remove-XmlNamespace -EA 0
  717. #Set-Alias rmxns Remove-XmlNamespace -EA 0
  718.  
  719. function Get-Namespace {
  720. param(
  721.    [Parameter(Position=0)]
  722.    [String[]]$Prefix = "*"
  723. ,
  724.    [Parameter(Position=1,ParameterSetName="Xml",Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  725.    [ValidateNotNullOrEmpty()]
  726.    [Alias("Node")]
  727.    [System.Xml.XmlNode[]]$Xml
  728. )
  729.    foreach($Node in @($Xml)) {
  730.       $results = @{}
  731.       if($Node -is [Xml.XmlDocument]) {
  732.          $Node = $Node.DocumentElement
  733.       }
  734.       foreach($ns in $Node.CreateNavigator().GetNamespacesInScope("All").GetEnumerator()) {
  735.          foreach($p in $Prefix) {
  736.             if($ns.Key -like $p) {
  737.                $results.Add($ns.Key, $ns.Value)
  738.                break;
  739.             }
  740.          }
  741.       }
  742.       $results
  743.    }
  744. }
  745.  
  746.  
  747.  
  748. ######## Helper functions for working with CliXml
  749.  
  750. function ConvertFrom-CliXml {
  751.    param(
  752.       [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
  753.       [ValidateNotNullOrEmpty()]
  754.       [String[]]$InputObject
  755.    )
  756.    begin
  757.    {
  758.       $OFS = "`n"
  759.       [String]$xmlString = ""
  760.    }
  761.    process
  762.    {
  763.       $xmlString += $InputObject
  764.    }
  765.    end
  766.    {
  767.       $type = [psobject].assembly.gettype("System.Management.Automation.Deserializer")
  768.       $ctor = $type.getconstructor("instance,nonpublic", $null, @([xml.xmlreader]), $null)
  769.       $sr = new-object System.IO.StringReader $xmlString
  770.       $xr = new-object System.Xml.XmlTextReader $sr
  771.       $deserializer = $ctor.invoke($xr)
  772.       $method = @($type.getmethods("nonpublic,instance") | where-object {$_.name -like "Deserialize"})[1]
  773.       $done = $type.getmethod("Done", [System.Reflection.BindingFlags]"nonpublic,instance")
  774.       while (!$done.invoke($deserializer, @()))
  775.       {
  776.          try {
  777.             $method.invoke($deserializer, "")
  778.          } catch {
  779.             write-warning "Could not deserialize $xmlString"
  780.          }
  781.       }
  782.       $xr.Close()
  783.       $sr.Dispose()
  784.    }
  785. }
  786.  
  787. function ConvertTo-CliXml {
  788.    param(
  789.       [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
  790.       [ValidateNotNullOrEmpty()]
  791.       [PSObject[]]$InputObject
  792.    )
  793.    begin {
  794.       $type = [psobject].assembly.gettype("System.Management.Automation.Serializer")
  795.       $ctor = $type.getconstructor("instance,nonpublic", $null, @([System.Xml.XmlWriter]), $null)
  796.       $sw = new-object System.IO.StringWriter
  797.       $xw = new-object System.Xml.XmlTextWriter $sw
  798.       $serializer = $ctor.invoke($xw)
  799.       $method = $type.getmethod("Serialize", "nonpublic,instance", $null, [type[]]@([object]), $null)
  800.       $done = $type.getmethod("Done", [System.Reflection.BindingFlags]"nonpublic,instance")
  801.    }
  802.    process {
  803.       try {
  804.          [void]$method.invoke($serializer, $InputObject)
  805.       } catch {
  806.          write-warning "Could not serialize $($InputObject.gettype()): $InputObject"
  807.       }
  808.    }
  809.    end {    
  810.       [void]$done.invoke($serializer, @())
  811.       $sw.ToString()
  812.       $xw.Close()
  813.       $sw.Dispose()
  814.    }
  815. }
  816.  
  817.  
  818. ######## From here down is all the code related to my XML DSL:
  819.  
  820. function New-XDocument {
  821. #.Synopsis
  822. #   Creates a new XDocument (the new xml document type)
  823. #.Description
  824. #  This is the root for a new XML mini-dsl, akin to New-BootsWindow for XAML
  825. #  It creates a new XDocument, and takes scritpblock(s) to define it's contents
  826. #.Example
  827. # [string]$xml = New-XDocument rss -version "2.0" {
  828. #    channel {
  829. #       title {"Test RSS Feed"}
  830. #       link {"http`://HuddledMasses.org"}
  831. #       description {"An RSS Feed generated simply to demonstrate my XML DSL"}
  832. #       item {
  833. #          title {"The First Item"}
  834. #          link {"http`://huddledmasses.org/new-site-new-layout-lost-posts/"}
  835. #          guid -isPermaLink true {"http`://huddledmasses.org/new-site-new-layout-lost-posts/"}
  836. #          description {"Ema Lazarus' Poem"}
  837. #          pubDate {(Get-Date 10/31/2003 -f u) -replace " ","T"}
  838. #       }
  839. #    }
  840. # }
  841. #
  842. # C:\PS>$xml.Declaration.ToString()  ## I can't find a way to have this included in the $xml.ToString()
  843. # C:\PS>$xml.ToString()
  844. #
  845. # <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  846. # <rss version="2.0">
  847. #   <channel>
  848. #     <title>Test RSS Feed</title>
  849. #     <link>http ://HuddledMasses.org</link>
  850. #     <description>An RSS Feed generated simply to demonstrate my XML DSL</description>
  851. #     <item>
  852. #       <title>The First Item</title>
  853. #       <link>http ://huddledmasses.org/new-site-new-layout-lost-posts/</link>
  854. #       <guid isPermaLink="true">http ://huddledmasses.org/new-site-new-layout-lost-posts/</guid>
  855. #       <description>Ema Lazarus' Poem</description>
  856. #       <pubDate>2003-10-31T00:00:00Z</pubDate>
  857. #     </item>
  858. #   </channel>
  859. # </rss>
  860. #
  861. #
  862. # Description
  863. # -----------
  864. # This example shows the creation of a complete RSS feed with a single item in it.
  865. #
  866. # NOTE that the backtick in the http`: in the URLs in the input is unecessary, and I added the space after the http: in the URLs  in the output -- these are accomodations to PoshCode's spam filter. Backticks are not need in the input, and spaces do not appear in the actual output.
  867. #
  868. #
  869. #.Example
  870. # [XNamespace]$atom="http`://www.w3.org/2005/Atom"
  871. # C:\PS>[XNamespace]$dc = "http`://purl.org/dc/elements/1.1"
  872. #
  873. # C:\PS>New-XDocument ($atom + "feed") -Encoding "UTF-16" -$([XNamespace]::Xml +'lang') "en-US" -dc $dc {
  874. #    title {"Test First Entry"}
  875. #    link {"http`://HuddledMasses.org"}
  876. #    updated {(Get-Date -f u) -replace " ","T"}
  877. #    author {
  878. #       name {"Joel Bennett"}
  879. #       uri {"http`://HuddledMasses.org"}
  880. #    }
  881. #    id {"http`://huddledmasses.org/" }
  882. #
  883. #    entry {
  884. #       title {"Test First Entry"}
  885. #       link {"http`://HuddledMasses.org/new-site-new-layout-lost-posts/" }
  886. #       id {"http`://huddledmasses.org/new-site-new-layout-lost-posts/" }
  887. #       updated {(Get-Date 10/31/2003 -f u) -replace " ","T"}
  888. #       summary {"Ema Lazarus' Poem"}
  889. #       link -rel license -href "http`://creativecommons.org/licenses/by/3.0/" -title "CC By-Attribution"
  890. #       dc:rights { "Copyright 2009, Some rights reserved (licensed under the Creative Commons Attribution 3.0 Unported license)" }
  891. #       category -scheme "http`://huddledmasses.org/tag/" -term "huddled-masses"
  892. #    }
  893. # } | % { $_.Declaration.ToString(); $_.ToString() }
  894. #
  895. # <?xml version="1.0" encoding="UTF-16" standalone="yes"?>
  896. # <feed xml:lang="en-US" xmlns="http ://www.w3.org/2005/Atom">
  897. #   <title>Test First Entry</title>
  898. #   <link>http ://HuddledMasses.org</link>
  899. #   <updated>2009-07-29T17:25:49Z</updated>
  900. #   <author>
  901. #      <name>Joel Bennett</name>
  902. #      <uri>http ://HuddledMasses.org</uri>
  903. #   </author>
  904. #   <id>http ://huddledmasses.org/</id>
  905. #   <entry>
  906. #     <title>Test First Entry</title>
  907. #     <link>http ://HuddledMasses.org/new-site-new-layout-lost-posts/</link>
  908. #     <id>http ://huddledmasses.org/new-site-new-layout-lost-posts/</id>
  909. #     <updated>2003-10-31T00:00:00Z</updated>
  910. #     <summary>Ema Lazarus' Poem</summary>
  911. #     <link rel="license" href="http ://creativecommons.org/licenses/by/3.0/" title="CC By-Attribution" />
  912. #     <dc:rights>Copyright 2009, Some rights reserved (licensed under the Creative Commons Attribution 3.0 Unported license)</dc:rights>
  913. #     <category scheme="http ://huddledmasses.org/tag/" term="huddled-masses" />
  914. #   </entry>
  915. # </feed>
  916. #
  917. #
  918. # Description
  919. # -----------
  920. # This example shows the use of a default namespace, as well as additional specific namespaces for the "dc" namespace. It also demonstrates how you can get the <?xml?> declaration which does not appear in a simple .ToString().
  921. #
  922. # NOTE that the backtick in the http`: in the URLs in the input is unecessary, and I added the space after the http: in the URLs  in the output -- these are accomodations to PoshCode's spam filter. Backticks are not need in the input, and spaces do not appear in the actual output.#
  923. #
  924. [CmdletBinding()]
  925. Param(
  926.    # The root node name
  927.    [Parameter(Mandatory = $true, Position = 0)]
  928.    [System.Xml.Linq.XName]$root
  929. ,
  930.    # Optional: the XML version. Defaults to 1.0
  931.    [Parameter(Mandatory = $false)]
  932.    [string]$Version = "1.0"
  933. ,
  934.    # Optional: the Encoding. Defaults to UTF-8
  935.    [Parameter(Mandatory = $false)]
  936.    [string]$Encoding = "UTF-8"
  937. ,
  938.    # Optional: whether to specify standalone in the xml declaration. Defaults to "yes"
  939.    [Parameter(Mandatory = $false)]
  940.    [string]$Standalone = "yes"
  941. ,
  942.    # A Hashtable of parameters which should be available as local variables to the scriptblock in args
  943.    [Parameter(Mandatory = $false)]
  944.    [hashtable]$Parameters
  945. ,
  946.    # this is where all the dsl magic happens. Please see the Examples. :)
  947.    [AllowNull()][AllowEmptyString()][AllowEmptyCollection()]
  948.    [Parameter(Position=99, Mandatory = $false, ValueFromRemainingArguments=$true)]
  949.    [PSObject[]]$args
  950. )
  951. BEGIN {
  952.    $script:NameSpaceHash = New-Object 'Dictionary[String,XNamespace]'
  953.    if($root.NamespaceName) {
  954.       $script:NameSpaceHash.Add("", $root.Namespace)
  955.    }
  956. }
  957. PROCESS {
  958.    if($Parameters) {
  959.       foreach($key in $Parameters.Keys) {
  960.          Set-Variable $key $Parameters.$key -Scope Script
  961.       }
  962.    }
  963.    New-Object XDocument (New-Object XDeclaration $Version, $Encoding, $standalone),(
  964.       New-Object XElement $(
  965.          $root
  966.          while($args) {
  967.             $attrib, $value, $args = $args
  968.             if($attrib -is [ScriptBlock]) {
  969.                # Write-Verbose "Preparsed DSL: $attrib"
  970.                $attrib = ConvertFrom-XmlDsl $attrib
  971.                Write-Verbose "Reparsed DSL: $attrib"
  972.                & $attrib
  973.             } elseif ( $value -is [ScriptBlock] -and "-CONTENT".StartsWith($attrib.TrimEnd(':').ToUpper())) {
  974.                $value = ConvertFrom-XmlDsl $value
  975.                Write-Verbose "Reparsed DSL: $value"
  976.                & $value
  977.             } elseif ( $value -is [XNamespace]) {
  978.                New-Object XAttribute ([XNamespace]::Xmlns + $attrib.TrimStart("-").TrimEnd(':')), $value
  979.                $script:NameSpaceHash.Add($attrib.TrimStart("-").TrimEnd(':'), $value)
  980.             } else {
  981.                Write-Verbose "XAttribute $attrib = $value"
  982.                New-Object XAttribute $attrib.TrimStart("-").TrimEnd(':'), $value
  983.             }
  984.          }
  985.       ))
  986. }
  987. }
  988.  
  989. Set-Alias xml New-XDocument -EA 0
  990. Set-Alias New-Xml New-XDocument -EA 0
  991.  
  992. function New-XAttribute {
  993. #.Synopsys
  994. #   Creates a new XAttribute (an xml attribute on an XElement for XDocument)
  995. #.Description
  996. #  This is the work-horse for the XML mini-dsl
  997. #.Parameter name
  998. #   The attribute name
  999. #.Parameter value
  1000. #  The attribute value
  1001. [CmdletBinding()]
  1002. Param([Parameter(Mandatory=$true)]$name,[Parameter(Mandatory=$true)]$value)
  1003.    New-Object XAttribute $name, $value
  1004. }
  1005. Set-Alias xa New-XAttribute -EA 0
  1006. Set-Alias New-XmlAttribute New-XAttribute -EA 0
  1007.  
  1008.  
  1009. function New-XElement {
  1010. #.Synopsys
  1011. #   Creates a new XElement (an xml tag for XDocument)
  1012. #.Description
  1013. #  This is the work-horse for the XML mini-dsl
  1014. #.Parameter tag
  1015. #   The name of the xml tag
  1016. #.Parameter args
  1017. #   this is where all the dsl magic happens. Please see the Examples. :)
  1018. [CmdletBinding()]
  1019. Param(
  1020.    [Parameter(Mandatory = $true, Position = 0)]
  1021.    [System.Xml.Linq.XName]$tag
  1022. ,
  1023.    [AllowNull()][AllowEmptyString()][AllowEmptyCollection()]
  1024.    [Parameter(Position=99, Mandatory = $false, ValueFromRemainingArguments=$true)]
  1025.    [PSObject[]]$args
  1026. )
  1027. PROCESS {
  1028.   New-Object XElement $(
  1029.      $tag
  1030.      Write-Verbose "New-XElement $tag $($args -join ',')"
  1031.      while($args) {
  1032.         $attrib, $value, $args = $args
  1033.         if($attrib -is [ScriptBlock]) { # then it's content
  1034.            & $attrib
  1035.         } elseif ( $value -is [ScriptBlock] -and "-CONTENT".StartsWith($attrib.TrimEnd(':').ToUpper())) { # then it's content
  1036.            & $value
  1037.         } elseif ( $value -is [XNamespace]) {
  1038.            Write-Verbose "New XAttribute xmlns: $($attrib.TrimStart("-").TrimEnd(':')) = $value"
  1039.            New-Object XAttribute ([XNamespace]::Xmlns + $attrib.TrimStart("-").TrimEnd(':')), $value
  1040.            $script:NameSpaceHash.Add($attrib.TrimStart("-").TrimEnd(':'), $value)
  1041.         } elseif($value -match "^-(?!\d)\w") {
  1042.             $args = @($value)+@($args)
  1043.         } elseif($value -ne $null) {
  1044.            Write-Verbose "New XAttribute $($attrib.TrimStart("-").TrimEnd(':')) = $value"
  1045.            New-Object XAttribute $attrib.TrimStart("-").TrimEnd(':'), $value
  1046.         }        
  1047.      }
  1048.    )
  1049. }
  1050. }
  1051. Set-Alias xe New-XElement
  1052. Set-Alias New-XmlElement New-XElement
  1053.  
  1054. function ConvertFrom-XmlDsl {
  1055. Param([ScriptBlock]$script)
  1056.    $parserrors = $null
  1057.    $global:tokens = [PSParser]::Tokenize( $script, [ref]$parserrors )
  1058.    [Array]$duds = $global:tokens | Where-Object { $_.Type -eq "Command" -and !$_.Content.Contains('-') -and ($(Get-Command $_.Content -Type Cmdlet,Function,ExternalScript -EA 0) -eq $Null) }
  1059.    if($duds) {
  1060.      [Array]::Reverse( $duds )
  1061.    }
  1062.    [string[]]$ScriptText = "$script" -split "`n"
  1063.  
  1064.    ForEach($token in $duds ) {
  1065.     # replace : notation with namespace notation
  1066.     if( $token.Content.Contains(":") ) {
  1067.      $key, $localname = $token.Content -split ":"
  1068.      $ScriptText[($token.StartLine - 1)] = $ScriptText[($token.StartLine - 1)].Remove( $token.StartColumn -1, $token.Length ).Insert( $token.StartColumn -1, "'" + $($script:NameSpaceHash[$key] + $localname) + "'" )
  1069.     } else {
  1070.      $ScriptText[($token.StartLine - 1)] = $ScriptText[($token.StartLine - 1)].Remove( $token.StartColumn -1, $token.Length ).Insert( $token.StartColumn -1, "'" + $($script:NameSpaceHash[''] + $token.Content) + "'" )
  1071.     }
  1072.     # insert 'xe' before everything (unless it's a valid command)
  1073.     $ScriptText[($token.StartLine - 1)] = $ScriptText[($token.StartLine - 1)].Insert( $token.StartColumn -1, "xe " )
  1074.    }
  1075.    Write-Output ([ScriptBlock]::Create( ($ScriptText -join "`n") ))
  1076. }
  1077.  
  1078.  
  1079.  
  1080. ######## Xaml
  1081. #  if($PSVersionTable.CLRVersion -ge "4.0"){
  1082. #     trap { continue }
  1083. #     [Reflection.Assembly]::LoadWithPartialName("System.Xaml") | Out-Null
  1084. #     if("System.Xaml.XamlServices" -as [type]) {
  1085.    
  1086.    #  }
  1087. #  }
  1088.    
  1089. Export-ModuleMember -alias * -function New-XDocument, New-XAttribute, New-XElement, Remove-XmlNamespace, Remove-XmlElement, Get-Namespace, Get-XmlContent, Set-XmlContent, Convert-Xml, Select-Xml, Update-Xml, Format-Xml, ConvertTo-CliXml, ConvertFrom-CliXml
  1090.  
  1091. # SIG # Begin signature block
  1092. # MIIfIAYJKoZIhvcNAQcCoIIfETCCHw0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
  1093. # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
  1094. # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUyHdevpWFnFH+l3PfnCoHIjum
  1095. # NvigghpSMIID7jCCA1egAwIBAgIQfpPr+3zGTlnqS5p31Ab8OzANBgkqhkiG9w0B
  1096. # AQUFADCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIG
  1097. # A1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhh
  1098. # d3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcg
  1099. # Q0EwHhcNMTIxMjIxMDAwMDAwWhcNMjAxMjMwMjM1OTU5WjBeMQswCQYDVQQGEwJV
  1100. # UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFu
  1101. # dGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMjCCASIwDQYJKoZIhvcN
  1102. # AQEBBQADggEPADCCAQoCggEBALGss0lUS5ccEgrYJXmRIlcqb9y4JsRDc2vCvy5Q
  1103. # WvsUwnaOQwElQ7Sh4kX06Ld7w3TMIte0lAAC903tv7S3RCRrzV9FO9FEzkMScxeC
  1104. # i2m0K8uZHqxyGyZNcR+xMd37UWECU6aq9UksBXhFpS+JzueZ5/6M4lc/PcaS3Er4
  1105. # ezPkeQr78HWIQZz/xQNRmarXbJ+TaYdlKYOFwmAUxMjJOxTawIHwHw103pIiq8r3
  1106. # +3R8J+b3Sht/p8OeLa6K6qbmqicWfWH3mHERvOJQoUvlXfrlDqcsn6plINPYlujI
  1107. # fKVOSET/GeJEB5IL12iEgF1qeGRFzWBGflTBE3zFefHJwXECAwEAAaOB+jCB9zAd
  1108. # BgNVHQ4EFgQUX5r1blzMzHSa1N197z/b7EyALt0wMgYIKwYBBQUHAQEEJjAkMCIG
  1109. # CCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMBIGA1UdEwEB/wQIMAYB
  1110. # Af8CAQAwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC50aGF3dGUuY29tL1Ro
  1111. # YXd0ZVRpbWVzdGFtcGluZ0NBLmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAOBgNV
  1112. # HQ8BAf8EBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0y
  1113. # MDQ4LTEwDQYJKoZIhvcNAQEFBQADgYEAAwmbj3nvf1kwqu9otfrjCR27T4IGXTdf
  1114. # plKfFo3qHJIJRG71betYfDDo+WmNI3MLEm9Hqa45EfgqsZuwGsOO61mWAK3ODE2y
  1115. # 0DGmCFwqevzieh1XTKhlGOl5QGIllm7HxzdqgyEIjkHq3dlXPx13SYcqFgZepjhq
  1116. # IhKjURmDfrYwggRPMIIDuKADAgECAgQHJ1g9MA0GCSqGSIb3DQEBBQUAMHUxCzAJ
  1117. # BgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdU
  1118. # RSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVy
  1119. # VHJ1c3QgR2xvYmFsIFJvb3QwHhcNMTAwMTEzMTkyMDMyWhcNMTUwOTMwMTgxOTQ3
  1120. # WjBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
  1121. # ExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3Vy
  1122. # YW5jZSBFViBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
  1123. # xszlc+b71LvlLS0ypt/lgT/JzSVJtnEqw9WUNGeiChywX2mmQLHEt7KP0JikqUFZ
  1124. # OtPclNY823Q4pErMTSWC90qlUxI47vNJbXGRfmO2q6Zfw6SE+E9iUb74xezbOJLj
  1125. # BuUIkQzEKEFV+8taiRV+ceg1v01yCT2+OjhQW3cxG42zxyRFmqesbQAUWgS3uhPr
  1126. # UQqYQUEiTmVhh4FBUKZ5XIneGUpX1S7mXRxTLH6YzRoGFqRoc9A0BBNcoXHTWnxV
  1127. # 215k4TeHMFYE5RG0KYAS8Xk5iKICEXwnZreIt3jyygqoOKsKZMK/Zl2VhMGhJR6H
  1128. # XRpQCyASzEG7bgtROLhLywIDAQABo4IBbzCCAWswEgYDVR0TAQH/BAgwBgEB/wIB
  1129. # ATBTBgNVHSAETDBKMEgGCSsGAQQBsT4BADA7MDkGCCsGAQUFBwIBFi1odHRwOi8v
  1130. # Y3liZXJ0cnVzdC5vbW5pcm9vdC5jb20vcmVwb3NpdG9yeS5jZm0wDgYDVR0PAQH/
  1131. # BAQDAgEGMIGJBgNVHSMEgYEwf6F5pHcwdTELMAkGA1UEBhMCVVMxGDAWBgNVBAoT
  1132. # D0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3QgU29sdXRp
  1133. # b25zLCBJbmMuMSMwIQYDVQQDExpHVEUgQ3liZXJUcnVzdCBHbG9iYWwgUm9vdIIC
  1134. # AaUwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29t
  1135. # L2NnaS1iaW4vQ1JMLzIwMTgvY2RwLmNybDAdBgNVHQ4EFgQUsT7DaQP4v0cB1Jgm
  1136. # GggC72NkK8MwDQYJKoZIhvcNAQEFBQADgYEALnaF2TeWba+J8wZ4gjHERgcfZcmO
  1137. # s8lUeObRQt91Lh5V6vf6mwTAdXvReTwF7HnEUt2mA9enUJk/BVnaxlX0hpwNZ6NJ
  1138. # BJUyHceH7IWvZG7VxV8Jp0B9FrpJDaL99t9VMGzXeMa5z1gpZBZMoyCBR7FEkoQW
  1139. # G29KvCHGCj3tM8owggSjMIIDi6ADAgECAhAOz/Q4yP6/NW4E2GqYGxpQMA0GCSqG
  1140. # SIb3DQEBBQUAMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jw
  1141. # b3JhdGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNl
  1142. # cyBDQSAtIEcyMB4XDTEyMTAxODAwMDAwMFoXDTIwMTIyOTIzNTk1OVowYjELMAkG
  1143. # A1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTQwMgYDVQQD
  1144. # EytTeW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIFNpZ25lciAtIEc0MIIB
  1145. # IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomMLOUS4uyOnREm7Dv+h8GEK
  1146. # U5OwmNutLA9KxW7/hjxTVQ8VzgQ/K/2plpbZvmF5C1vJTIZ25eBDSyKV7sIrQ8Gf
  1147. # 2Gi0jkBP7oU4uRHFI/JkWPAVMm9OV6GuiKQC1yoezUvh3WPVF4kyW7BemVqonShQ
  1148. # DhfultthO0VRHc8SVguSR/yrrvZmPUescHLnkudfzRC5xINklBm9JYDh6NIipdC6
  1149. # Anqhd5NbZcPuF3S8QYYq3AhMjJKMkS2ed0QfaNaodHfbDlsyi1aLM73ZY8hJnTrF
  1150. # xeozC9Lxoxv0i77Zs1eLO94Ep3oisiSuLsdwxb5OgyYI+wu9qU+ZCOEQKHKqzQID
  1151. # AQABo4IBVzCCAVMwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD
  1152. # CDAOBgNVHQ8BAf8EBAMCB4AwcwYIKwYBBQUHAQEEZzBlMCoGCCsGAQUFBzABhh5o
  1153. # dHRwOi8vdHMtb2NzcC53cy5zeW1hbnRlYy5jb20wNwYIKwYBBQUHMAKGK2h0dHA6
  1154. # Ly90cy1haWEud3Muc3ltYW50ZWMuY29tL3Rzcy1jYS1nMi5jZXIwPAYDVR0fBDUw
  1155. # MzAxoC+gLYYraHR0cDovL3RzLWNybC53cy5zeW1hbnRlYy5jb20vdHNzLWNhLWcy
  1156. # LmNybDAoBgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMjAd
  1157. # BgNVHQ4EFgQURsZpow5KFB7VTNpSYxc/Xja8DeYwHwYDVR0jBBgwFoAUX5r1blzM
  1158. # zHSa1N197z/b7EyALt0wDQYJKoZIhvcNAQEFBQADggEBAHg7tJEqAEzwj2IwN3ij
  1159. # hCcHbxiy3iXcoNSUA6qGTiWfmkADHN3O43nLIWgG2rYytG2/9CwmYzPkSWRtDebD
  1160. # Zw73BaQ1bHyJFsbpst+y6d0gxnEPzZV03LZc3r03H0N45ni1zSgEIKOq8UvEiCmR
  1161. # DoDREfzdXHZuT14ORUZBbg2w6jiasTraCXEQ/Bx5tIB7rGn0/Zy2DBYr8X9bCT2b
  1162. # W+IWyhOBbQAuOA2oKY8s4bL0WqkBrxWcLC9JG9siu8P+eJRRw4axgohd8D20UaF5
  1163. # Mysue7ncIAkTcetqGVvP6KUwVyyJST+5z3/Jvz4iaGNTmr1pdKzFHTx/kuDDvBzY
  1164. # BHUwggafMIIFh6ADAgECAhAOaQaYwhTIerW2BLkWPNGQMA0GCSqGSIb3DQEBBQUA
  1165. # MHMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT
  1166. # EHd3dy5kaWdpY2VydC5jb20xMjAwBgNVBAMTKURpZ2lDZXJ0IEhpZ2ggQXNzdXJh
  1167. # bmNlIENvZGUgU2lnbmluZyBDQS0xMB4XDTEyMDMyMDAwMDAwMFoXDTEzMDMyMjEy
  1168. # MDAwMFowbTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMRcwFQYDVQQH
  1169. # Ew5XZXN0IEhlbnJpZXR0YTEYMBYGA1UEChMPSm9lbCBILiBCZW5uZXR0MRgwFgYD
  1170. # VQQDEw9Kb2VsIEguIEJlbm5ldHQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
  1171. # AoIBAQDaiAYAbz13WMx9Em/Z3dTWUKxbyiTsaSOctgOfTMLUAurXWtY3k1XBVufX
  1172. # feL4pXQ7yQzm93YzvETwKdUCDJuOSu9EPYioy2nhKvBC6IaJUaw1VY7e9IsdxaxL
  1173. # 8js3RQilLk+FO4UHg9w7L8wdHgXaDoksysC2SlhbFq4AVl8XC4R+bq+pahsdMO3n
  1174. # Ab7Oo5PExKLVS8vl8QwOh6MaqquIjHmYoPOu9Rv8As0pnWsY9aVPs7T9QetXlW45
  1175. # +CKPhdUoEB1yD0kvGTIAQgn5W9VDYmfeVU40IIdt+7khWF10yu7zVT+/lauPzRmv
  1176. # CHZMfbmqVyVQqvp5dEu0/7EWbbcLAgMBAAGjggMzMIIDLzAfBgNVHSMEGDAWgBSX
  1177. # SAPrFQhrubJYI8yULvHGZdJkjjAdBgNVHQ4EFgQUmJxEqr9ewFZG4rNTp5NQIEIJ
  1178. # TrkwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMGkGA1UdHwRi
  1179. # MGAwLqAsoCqGKGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9oYS1jcy0yMDExYS5j
  1180. # cmwwLqAsoCqGKGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9oYS1jcy0yMDExYS5j
  1181. # cmwwggHEBgNVHSAEggG7MIIBtzCCAbMGCWCGSAGG/WwDATCCAaQwOgYIKwYBBQUH
  1182. # AgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5o
  1183. # dG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0
  1184. # AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1
  1185. # AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABp
  1186. # AGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBl
  1187. # AGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBo
  1188. # AGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAg
  1189. # AGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAg
  1190. # AGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wgYYGCCsGAQUFBwEBBHoweDAkBggr
  1191. # BgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFAGCCsGAQUFBzAChkRo
  1192. # dHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRIaWdoQXNzdXJhbmNl
  1193. # Q29kZVNpZ25pbmdDQS0xLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBBQUA
  1194. # A4IBAQAch95ik7Qm12L9Olwjp5ZAhhTYAs7zjtD3WMsTpaJTq7zA3q2QeqB46WzT
  1195. # vRINQr4LWtWhcopnQl5zaTV1i6Qo+TJ/epRE/KH9oLeEnRbBuN7t8rv0u31kfAk5
  1196. # Gl6wmvBrxPreXeossuU9ohij9uqIyk1lF85yW6QqDaE7rvIxpCXwMQv8PlQ/VdlK
  1197. # EXbNtq4frbvMQLkpcZljbJRuZYbY3SgfGv6rgbJ93Qw+1Tlq9Y4gsHRmw35uv5IJ
  1198. # VUrqcrNq5cyTgdeYodpftzKyqmZCIVvv8nu09DTfspAocJj9n5+XRqtEKIeKH9D/
  1199. # mjC/nVZIo+JpSuQG90nSYpUr4xwfMIIGvzCCBaegAwIBAgIQCBxX7l1w65ugsVIM
  1200. # cpwbCTANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln
  1201. # aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJE
  1202. # aWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTExMDIxMDEyMDAw
  1203. # MFoXDTI2MDIxMDEyMDAwMFowczELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD
  1204. # ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEyMDAGA1UEAxMpRGln
  1205. # aUNlcnQgSGlnaCBBc3N1cmFuY2UgQ29kZSBTaWduaW5nIENBLTEwggEiMA0GCSqG
  1206. # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDF+SPmlCfEgBSkgDJfQKONb3DA5TZxcTp1
  1207. # pKoakpSJXqwjcctOZ31BP6rjS7d7vp3BqDiPaS86JOl3WRLHZgRDwg0mgolAGfIs
  1208. # 6udM53wFGrj/iAlPJjfvOqT6ImyIyUobYfKuEF5vvNF5m1kYYOXuKbUDKqTO8YMZ
  1209. # T2kFcygJ+yIQkyKgkBkaTDHy0yvYhEOvPGP/mNsg0gkrVMHq/WqD5xCjEnH11tfh
  1210. # EnrV4FZazuoBW2hlW8E/WFIzqTVhTiLLgco2oxLLBtbPG00YfrmSuRLPQCbYmjaF
  1211. # sxWqR5OEawe7vNWz3iUAEYkAaMEpPOo+Le5Qq9ccMAZ4PKUQI2eRAgMBAAGjggNU
  1212. # MIIDUDAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwggHDBgNV
  1213. # HSAEggG6MIIBtjCCAbIGCGCGSAGG/WwDMIIBpDA6BggrBgEFBQcCARYuaHR0cDov
  1214. # L3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsG
  1215. # AQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABD
  1216. # AGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABh
  1217. # AGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQBy
  1218. # AHQAIABFAFYAIABDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBn
  1219. # ACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABs
  1220. # AGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABp
  1221. # AG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBl
  1222. # AGYAZQByAGUAbgBjAGUALjAPBgNVHRMBAf8EBTADAQH/MH8GCCsGAQUFBwEBBHMw
  1223. # cTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEkGCCsGAQUF
  1224. # BzAChj1odHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRIaWdoQXNz
  1225. # dXJhbmNlRVZSb290Q0EuY3J0MIGPBgNVHR8EgYcwgYQwQKA+oDyGOmh0dHA6Ly9j
  1226. # cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5j
  1227. # cmwwQKA+oDyGOmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hB
  1228. # c3N1cmFuY2VFVlJvb3RDQS5jcmwwHQYDVR0OBBYEFJdIA+sVCGu5slgjzJQu8cZl
  1229. # 0mSOMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEB
  1230. # BQUAA4IBAQCCBemFr6dMv6/OPbLqYLFo3mfC0ssm4MMvm7VrDlOQhfab4DUC//pp
  1231. # g6q0dDIUPC4QTCibCq0ICfnzhBGTj8tgQFbpdy9psoOZVatHJJbLf0uwELSXv8Sl
  1232. # mQb+juwUUB5eV5fLR7k02fw6ov9QKcIKYgTu3pY6b6DChQ9v/AjkMnvThK5pYAlG
  1233. # Jpzo8P//htnICTpmw6c2jxhP6LGWki5OvgunM5CuvG5P8X6NtEYOZPlZBiIhZABL
  1234. # 4noIA+e8iZCeQk8BwLYWf3XqRrKlVC+Mk80RNjRqKFfMlD/pfMgYAwMEfkPa+Zeh
  1235. # WUfaEqrgbTgAXTUrxSKGywbKvHpNPSZGMYIEODCCBDQCAQEwgYcwczELMAkGA1UE
  1236. # BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj
  1237. # ZXJ0LmNvbTEyMDAGA1UEAxMpRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2UgQ29kZSBT
  1238. # aWduaW5nIENBLTECEA5pBpjCFMh6tbYEuRY80ZAwCQYFKw4DAhoFAKB4MBgGCisG
  1239. # AQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
  1240. # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFPiX
  1241. # pwIkB3/2bW1OEputr5R6783fMA0GCSqGSIb3DQEBAQUABIIBAAPtJvZK1hsDyqw8
  1242. # IcPfF76/2UJL+eYQocJ4cRzW3Qzm7oaIe+Co/Wruxrz6wWGztKJIqG8mf/Yj9Eqt
  1243. # mlYyYQo2ra67G3OotFQZHI/KWe+HaYZx86czL9xv/pWpSvwecQsYD2YhM7Hi0Dfl
  1244. # wWtmOLJ0U+pedrQP8goXiXj70rBfFwl+yz7KkiPHrUANETbcfxUWt83INRJ/tgcq
  1245. # dV3h1vLfrPJPAw5YZ3SBD5n5NYfm790knKFHCnVCzjcgbpoeX0aVsBCUzs+orKkX
  1246. # zbNJOr0vG9B0vBqBBkwYkCFfurn9Bc24D9V/QCO7QpFdHL0MlRKq8O3D9meXGjNM
  1247. # vvp0IqahggILMIICBwYJKoZIhvcNAQkGMYIB+DCCAfQCAQEwcjBeMQswCQYDVQQG
  1248. # EwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5
  1249. # bWFudGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMgIQDs/0OMj+vzVu
  1250. # BNhqmBsaUDAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAc
  1251. # BgkqhkiG9w0BCQUxDxcNMTMwMjAxMDY0ODQzWjAjBgkqhkiG9w0BCQQxFgQUm5wB
  1252. # DUFZvs+FwkJDoGcS62LO/lUwDQYJKoZIhvcNAQEBBQAEggEAXfq9dni7R3tT/jdw
  1253. # OfYO5EyK4BaR1GBy7q2tu280sZ+n4H6H88IEoIr4QokmyN2em3Dq8t4FQobzIG+n
  1254. # iW3Wg5GKD3Ijo9jcjz0CpvXVUqAq302BfhPxGKfVhhSlVOcOa1kCBfk/bQ8vFjYt
  1255. # O+LY7h/sa2t1MlrChcoSr3rcc5GUOFx2jTLnLXWLSpGVsOyaCnont5aM97HUmE8+
  1256. # NSYLET+4AIyJCTBVjL+6ERm7z9/ZqfTwy1pYcTnDJaV8ALqyjU/WVpMmlLFvPYnS
  1257. # ic/nKDE0HR7dOujxpMQsp816y1wWIZqWMOOMkUsz4SF9lJP31/ErE6EjaYIGQFQe
  1258. # KFsXtQ==
  1259. # SIG # End signature block

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me