PoshCode Logo PowerShell Code Repository

Xml Module 3 by Joel Bennett 23 months ago (modification of post by Joel Bennett view diff)
View followups from Joel Bennett | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1675"></script>download | new post

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. Note that this means that the returned results will not have namespaces in them, even if the input XML did.

Also, 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

  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 was the first script version I wrote, and it didn't function identically to the built-in Select-Xml with regards to parameter parsing
  13. # Select-Xml 2.1 matched the built-in Select-Xml parameter sets, it's now a drop-in replacement if you were using the original with: Select-Xml ... | Select-Object -Expand Node
  14. # Select-Xml 2.2 fixes a bug in the -Content parameterset where -RemoveNamespace was *presumed*
  15. # Added New-Xml and associated generation functions for my XML DSL
  16.  
  17.  
  18. $xlr8r = [type]::gettype("System.Management.Automation.TypeAccelerators")
  19. $xlinq = [Reflection.Assembly]::Load("System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
  20. $xlinq.GetTypes() | ? { $_.IsPublic -and !$_.IsSerializable -and $_.Name -ne "Extensions" -and !$xlr8r::Get[$_.Name] } | % {
  21.   $xlr8r::Add( $_.Name, $_.FullName )
  22. }
  23.  
  24. function Format-XML {
  25. #.Synopsis
  26. #   Pretty-print formatted XML source
  27. #.Description
  28. #       Runs an XmlDocument through an auto-indenting XmlWriter
  29. #.Parameter Xml
  30. #       The Xml Document
  31. #.Parameter Indent
  32. #       The indent level (defaults to 2 spaces)
  33. Param(
  34.         [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true)]
  35.         [xml]$xml
  36. ,
  37.         [Parameter(Mandatory=$false)]
  38.         $indent=2
  39. )
  40.     $StringWriter = New-Object System.IO.StringWriter
  41.     $XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter
  42.     $xmlWriter.Formatting = "indented"
  43.     $xmlWriter.Indentation = $Indent
  44.     $xml.WriteContentTo($XmlWriter)
  45.     $XmlWriter.Flush()
  46.     $StringWriter.Flush()
  47.     Write-Output $StringWriter.ToString()
  48. }
  49. Set-Alias fxml Format-Xml -Option AllScope
  50.  
  51. function Select-Xml {
  52. #.Synopsis
  53. #  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.
  54. #.Description
  55. #  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.  
  56. #  
  57. #  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
  58. #
  59. #  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.
  60. #.Parameter Content
  61. #  Specifies a string that contains the XML to search. You can also pipe strings to Select-XML.
  62. #.Parameter Namespace
  63. #   Specifies a hash table of the namespaces used in the XML. Use the format @{<namespaceName> = <namespaceUri>}.
  64. #.Parameter Path
  65. #   Specifies the path and file names of the XML files to search.  Wildcards are permitted.
  66. #.Parameter Xml
  67. #  Specifies one or more XML nodes to search.
  68. #.Parameter XPath
  69. #  Specifies an XPath search query. The query language is case-sensitive. This parameter is required.
  70. #.Parameter RemoveNamespace
  71. #  Allows the execution of XPath queries without namespace qualifiers.
  72. #  
  73. #  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.
  74. #
  75. #  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.
  76. [CmdletBinding(DefaultParameterSetName="Xml")]
  77. PARAM(
  78.    [Parameter(Position=1,ParameterSetName="Path",Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
  79.    [ValidateNotNullOrEmpty()]
  80.    [Alias("PSPath")]
  81.    [String[]]$Path
  82. ,
  83.    [Parameter(Position=1,ParameterSetName="Xml",Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  84.    [ValidateNotNullOrEmpty()]
  85.    [Alias("Node")]
  86.    [System.Xml.XmlNode[]]$Xml
  87. ,
  88.    [Parameter(ParameterSetName="Content",Mandatory=$true,ValueFromPipeline=$true)]
  89.    [ValidateNotNullOrEmpty()]
  90.    [String[]]$Content
  91. ,
  92.    [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false)]
  93.    [ValidateNotNullOrEmpty()]
  94.    [Alias("Query")]
  95.    [String[]]$XPath
  96. ,
  97.    [Parameter(Mandatory=$false)]
  98.    [ValidateNotNullOrEmpty()]
  99.    [Hashtable]$Namespace
  100. ,
  101.    [Switch]$RemoveNamespace
  102. )
  103. BEGIN {
  104.    function Select-Node {
  105.    PARAM([Xml.XmlNode]$Xml, [String[]]$XPath, $NamespaceManager)
  106.    BEGIN {
  107.       foreach($node in $xml) {
  108.          if($NamespaceManager -is [Hashtable]) {
  109.             $nsManager = new-object System.Xml.XmlNamespaceManager $node.NameTable
  110.             foreach($ns in $Namespace.GetEnumerator()) {
  111.                $nsManager.AddNamespace( $ns.Key, $ns.Value )
  112.             }
  113.          }
  114.          
  115.          foreach($path in $xpath) {
  116.             $node.SelectNodes($path, $NamespaceManager)
  117.    }  }  }  }
  118.  
  119.    [Text.StringBuilder]$XmlContent = [String]::Empty
  120. }
  121.  
  122. PROCESS {
  123.    $NSM = $Null; if($PSBoundParameters.ContainsKey("Namespace")) { $NSM = $Namespace }
  124.  
  125.    switch($PSCmdlet.ParameterSetName) {
  126.       "Content" {
  127.          $null = $XmlContent.AppendLine( $Content -Join "`n" )
  128.       }
  129.       "Path" {
  130.          foreach($file in Get-ChildItem $Path) {
  131.             [Xml]$Xml = Get-Content $file
  132.             if($RemoveNamespace) {
  133.                $Xml = Remove-XmlNamespace $Xml
  134.             }
  135.             Select-Node $Xml $XPath  $NSM
  136.          }
  137.       }
  138.       "Xml" {
  139.          foreach($node in $Xml) {
  140.             if($RemoveNamespace) {
  141.                $node = Remove-XmlNamespace $node
  142.             }
  143.             Select-Node $node $XPath $NSM
  144.          }
  145.       }
  146.    }
  147. }
  148. END {
  149.    if($PSCmdlet.ParameterSetName -eq "Content") {
  150.       [Xml]$Xml = $XmlContent.ToString()
  151.       if($RemoveNamespace) {
  152.          $Xml = Remove-XmlNamespace $Xml
  153.       }
  154.       Select-Node $Xml $XPath  $NSM
  155.    }
  156. }
  157.  
  158. }
  159. Set-Alias slxml Select-Xml -Option AllScope
  160.  
  161. function Convert-Node {
  162. #.Synopsis
  163. # Convert a single XML Node via XSL stylesheets
  164. param(
  165. [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
  166. [System.Xml.XmlReader]$XmlReader,
  167. [Parameter(Position=1,Mandatory=$true,ValueFromPipeline=$false)]
  168. [System.Xml.Xsl.XslCompiledTransform]$StyleSheet
  169. )
  170. PROCESS {
  171.    $output = New-Object IO.StringWriter
  172.    $StyleSheet.Transform( $XmlReader, $null, $output )
  173.    Write-Output $output.ToString()
  174. }
  175. }
  176.    
  177. function Convert-Xml {
  178. #.Synopsis
  179. #  The Convert-XML function lets you use Xslt to transform XML strings and documents.
  180. #.Description
  181. #.Parameter Content
  182. #  Specifies a string that contains the XML to search. You can also pipe strings to Select-XML.
  183. #.Parameter Namespace
  184. #   Specifies a hash table of the namespaces used in the XML. Use the format @{<namespaceName> = <namespaceUri>}.
  185. #.Parameter Path
  186. #   Specifies the path and file names of the XML files to search.  Wildcards are permitted.
  187. #.Parameter Xml
  188. #  Specifies one or more XML nodes to search.
  189. #.Parameter Xsl
  190. #  Specifies an Xml StyleSheet to transform with...
  191. [CmdletBinding(DefaultParameterSetName="Xml")]
  192. PARAM(
  193.    [Parameter(Position=1,ParameterSetName="Path",Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
  194.    [ValidateNotNullOrEmpty()]
  195.    [Alias("PSPath")]
  196.    [String[]]$Path
  197. ,
  198.    [Parameter(Position=1,ParameterSetName="Xml",Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  199.    [ValidateNotNullOrEmpty()]
  200.    [Alias("Node")]
  201.    [System.Xml.XmlNode[]]$Xml
  202. ,
  203.    [Parameter(ParameterSetName="Content",Mandatory=$true,ValueFromPipeline=$true)]
  204.    [ValidateNotNullOrEmpty()]
  205.    [String[]]$Content
  206. ,
  207.    [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false)]
  208.    [ValidateNotNullOrEmpty()]
  209.    [Alias("StyleSheet")]
  210.    [String[]]$Xslt
  211. )
  212. BEGIN {
  213.    $StyleSheet = New-Object System.Xml.Xsl.XslCompiledTransform
  214.    if(Test-Path @($Xslt)[0] -EA 0) {
  215.       Write-Verbose "Loading Stylesheet from $(Resolve-Path @($Xslt)[0])"
  216.       $StyleSheet.Load( (Resolve-Path @($Xslt)[0]) )
  217.    } else {
  218.       Write-Verbose "$Xslt"
  219.       $StyleSheet.Load(([System.Xml.XmlReader]::Create((New-Object System.IO.StringReader ($Xslt -join "`n")))))
  220.    }
  221.    [Text.StringBuilder]$XmlContent = [String]::Empty
  222. }
  223. PROCESS {
  224.    switch($PSCmdlet.ParameterSetName) {
  225.       "Content" {
  226.          $null = $XmlContent.AppendLine( $Content -Join "`n" )
  227.       }
  228.       "Path" {
  229.          foreach($file in Get-ChildItem $Path) {
  230.             Convert-Node -Xml ([System.Xml.XmlReader]::Create((Resolve-Path $file))) $StyleSheet
  231.          }
  232.       }
  233.       "Xml" {
  234.          foreach($node in $Xml) {
  235.             Convert-Node -Xml (New-Object Xml.XmlNodeReader $node) $StyleSheet
  236.          }
  237.       }
  238.    }
  239. }
  240. END {
  241.    if($PSCmdlet.ParameterSetName -eq "Content") {
  242.       [Xml]$Xml = $XmlContent.ToString()
  243.       Convert-Node -Xml $Xml $StyleSheet
  244.    }
  245. }
  246. }
  247. Set-Alias cvxml Convert-Xml -Option AllScope
  248.  
  249. function Remove-XmlNamespace {
  250. #.Synopsis
  251. #  Removes namespace definitions and prefixes from xml documents
  252. #.Description
  253. #  Runs an xml document through an XSL Transformation to remove namespaces from it if they exist.
  254. #  Entities are also naturally expanded
  255. #.Parameter Content
  256. #  Specifies a string that contains the XML to transform.
  257. #.Parameter Path
  258. #  Specifies the path and file names of the XML files to transform. Wildcards are permitted.
  259. #
  260. #  There will bne one output document for each matching input file.
  261. #.Parameter Xml
  262. #  Specifies one or more XML documents to transform
  263. [CmdletBinding(DefaultParameterSetName="Xml")]
  264. PARAM(
  265.    [Parameter(Position=1,ParameterSetName="Path",Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
  266.    [ValidateNotNullOrEmpty()]
  267.    [Alias("PSPath")]
  268.    [String[]]$Path
  269. ,
  270.    [Parameter(Position=1,ParameterSetName="Xml",Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  271.    [ValidateNotNullOrEmpty()]
  272.    [Alias("Node")]
  273.    [System.Xml.XmlNode[]]$Xml
  274. ,
  275.    [Parameter(ParameterSetName="Content",Mandatory=$true,ValueFromPipeline=$true)]
  276.    [ValidateNotNullOrEmpty()]
  277.    [String[]]$Content
  278. ,
  279.    [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false)]
  280.    [ValidateNotNullOrEmpty()]
  281.    [Alias("StyleSheet")]
  282.    [String[]]$Xslt
  283. )
  284. BEGIN {
  285.    $StyleSheet = New-Object System.Xml.Xsl.XslCompiledTransform
  286.    $StyleSheet.Load(([System.Xml.XmlReader]::Create((New-Object System.IO.StringReader @"
  287. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  288.   <xsl:output method="xml" indent="yes"/>
  289.   <xsl:template match="/|comment()|processing-instruction()">
  290.      <xsl:copy>
  291.         <xsl:apply-templates/>
  292.      </xsl:copy>
  293.   </xsl:template>
  294.  
  295.   <xsl:template match="*">
  296.      <xsl:element name="{local-name()}">
  297.         <xsl:apply-templates select="@*|node()"/>
  298.      </xsl:element>
  299.   </xsl:template>
  300.  
  301.   <xsl:template match="@*">
  302.      <xsl:attribute name="{local-name()}">
  303.         <xsl:value-of select="."/>
  304.      </xsl:attribute>
  305.   </xsl:template>
  306. </xsl:stylesheet>
  307. "@))))
  308.    [Text.StringBuilder]$XmlContent = [String]::Empty
  309. }
  310. PROCESS {
  311.    switch($PSCmdlet.ParameterSetName) {
  312.       "Content" {
  313.          $null = $XmlContent.AppendLine( $Content -Join "`n" )
  314.       }
  315.       "Path" {
  316.          foreach($file in Get-ChildItem $Path) {
  317.             [Xml]$Xml = Get-Content $file
  318.             Convert-Node -Xml $Xml $StyleSheet
  319.          }
  320.       }
  321.       "Xml" {
  322.          $Xml | Convert-Node $StyleSheet
  323.       }
  324.    }
  325. }
  326. END {
  327.    if($PSCmdlet.ParameterSetName -eq "Content") {
  328.       [Xml]$Xml = $XmlContent.ToString()
  329.       Convert-Node -Xml $Xml $StyleSheet
  330.    }
  331. }
  332. }
  333. Set-Alias rmns Remove-XmlNamespace -Option AllScope
  334.  
  335. function New-XDocument {
  336. #.Synopsys
  337. #       Creates a new XDocument (the new xml document type)
  338. #.Description
  339. #  This is the root for a new XML mini-dsl, akin to New-BootsWindow for XAML
  340. #  It creates a new XDocument, and takes scritpblock(s) to define it's contents
  341. #.Parameter root
  342. #       The root node name
  343. #.Parameter version
  344. #       Optional: the XML version. Defaults to 1.0
  345. #.Parameter encoding
  346. #       Optional: the Encoding. Defaults to UTF-8
  347. #.Parameter standalone
  348. #  Optional: whether to specify standalone in the xml declaration. Defaults to "yes"
  349. #.Parameter args
  350. #       this is where all the dsl magic happens. Please see the Examples. :)
  351. #
  352. #.Example
  353. # [XNamespace]$dc = "http`://purl.org/dc/elements/1.1"
  354. # $xml = New-XDocument rss -dc $dc -version "2.0" {
  355. #    xe channel {
  356. #       xe title {"Test RSS Feed"}
  357. #       xe link {"http`://HuddledMasses.org"}
  358. #       xe description {"An RSS Feed generated simply to demonstrate my XML DSL"}
  359. #       xe ($dc + "language") {"en"}
  360. #       xe ($dc + "creator") {"Jaykul@HuddledMasses.org"}
  361. #       xe ($dc + "rights") {"Copyright 2009, CC-BY"}
  362. #       xe ($dc + "date") {(Get-Date -f u) -replace " ","T"}
  363. #       xe item {
  364. #          xe title {"The First Item"}
  365. #          xe link {"http`://huddledmasses.org/new-site-new-layout-lost-posts/"}
  366. #          xe guid -isPermaLink true {"http`://huddledmasses.org/new-site-new-layout-lost-posts/"}
  367. #          xe description {"Ema Lazarus' Poem"}
  368. #          xe pubDate  {(Get-Date 10/31/2003 -f u) -replace " ","T"}
  369. #       }
  370. #    }
  371. # }
  372. #
  373. # $xml.Declaration.ToString()  ## I can't find a way to have this included in the $xml.ToString()
  374. # $xml.ToString()
  375. #
  376. #
  377. # OUTPUT: (NOTE: I added the space in the http: to paste it on PoshCode -- those aren't in the output)
  378. #
  379. #
  380. # <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  381. # <rss xmlns:dc="http ://purl.org/dc/elements/1.1" version="2.0">
  382. #   <channel>
  383. #     <title>Test RSS Feed</title>
  384. #     <link>http ://HuddledMasses.org</link>
  385. #     <description>An RSS Feed generated simply to demonstrate my XML DSL</description>
  386. #     <dc:language>en</dc:language>
  387. #     <dc:creator>Jaykul@HuddledMasses.org</dc:creator>
  388. #     <dc:rights>Copyright 2009, CC-BY</dc:rights>
  389. #     <dc:date>2009-07-26T00:50:08Z</dc:date>
  390. #     <item>
  391. #       <title>The First Item</title>
  392. #       <link>http ://huddledmasses.org/new-site-new-layout-lost-posts/</link>
  393. #       <guid isPermaLink="true">http ://huddledmasses.org/new-site-new-layout-lost-posts/</guid>
  394. #       <description>Ema Lazarus' Poem</description>
  395. #       <pubDate>2003-10-31T00:00:00Z</pubDate>
  396. #     </item>
  397. #   </channel>
  398. # </rss>
  399. #
  400. #.Example
  401. #  This time with a default namespace
  402. ## IMPORTANT! ## NOTE that I use the "xe" shortcut which is redefined when you specify a namespace
  403. ##            ## for the root element, so that all child elements (by default) inherit that.
  404. ##            ## You can still control the prefixes by passing the namespace as a parameter
  405. ##            ## e.g.: -atom $atom
  406. ## The `: in the http`: is still only there for PoshCode, you can just use http: ...
  407. #
  408. #   [XNamespace]$atom="http`://www.w3.org/2005/Atom"
  409. #   [XNamespace]$dc = "http`://purl.org/dc/elements/1.1"
  410. #  
  411. #   New-Xml ($atom + "feed") -Encoding "UTF-16" -$([XNamespace]::Xml +'lang') "en-US" -dc $dc {
  412. #      xe title {"Test First Entry"}
  413. #      xe link {"http`://HuddledMasses.org"}
  414. #      xe updated {(Get-Date -f u) -replace " ","T"}
  415. #      xe author {
  416. #         xe name {"Joel Bennett"}
  417. #         xe uri {"http`://HuddledMasses.org"}
  418. #      }
  419. #      xe id {"http`://huddledmasses.org/" }
  420. #
  421. #      xe entry {
  422. #         xe title {"Test First Entry"}
  423. #         xe link {"http`://HuddledMasses.org/new-site-new-layout-lost-posts/" }
  424. #         xe id {"http`://huddledmasses.org/new-site-new-layout-lost-posts/" }
  425. #         xe updated {(Get-Date 10/31/2003 -f u) -replace " ","T"}
  426. #         xe summary {"Ema Lazarus' Poem"}
  427. #         xe link -rel license -href "http://creativecommons.org/licenses/by/3.0/" -title "CC By-Attribution"
  428. #         xe ($dc + "rights") {"Copyright 2009, Some rights reserved (licensed under the Creative Commons Attribution 3.0 Unported license)"}
  429. #         xe category -scheme "http://huddledmasses.org/tag/" -term "huddled-masses"
  430. #      }
  431. #   } | % { $_.Declaration.ToString(); $_.ToString() }
  432. #
  433. #
  434. #  OUTPUT: (NOTE: I added the spaces again to the http: to paste it on PoshCode)
  435. #
  436. #
  437. # <?xml version="1.0" encoding="UTF-16" standalone="yes"?>
  438. # <feed xml:lang="en-US" xmlns="http ://www.w3.org/2005/Atom">
  439. #   <title>Test First Entry</title>
  440. #   <link>http ://HuddledMasses.org</link>
  441. #   <updated>2009-07-29T17:25:49Z</updated>
  442. #   <author>
  443. #      <name>Joel Bennett</name>
  444. #      <uri>http ://HuddledMasses.org</uri>
  445. #   </author>
  446. #   <id>http ://huddledmasses.org/</id>
  447. #   <entry>
  448. #     <title>Test First Entry</title>
  449. #     <link>http ://HuddledMasses.org/new-site-new-layout-lost-posts/</link>
  450. #     <id>http ://huddledmasses.org/new-site-new-layout-lost-posts/</id>
  451. #     <updated>2003-10-31T00:00:00Z</updated>
  452. #     <summary>Ema Lazarus' Poem</summary>
  453. #     <link rel="license" href="http ://creativecommons.org/licenses/by/3.0/" title="CC By-Attribution" />
  454. #     <dc:rights>Copyright 2009, Some rights reserved (licensed under the Creative Commons Attribution 3.0 Unported license)</dc:rights>
  455. #     <category scheme="http ://huddledmasses.org/tag/" term="huddled-masses" />
  456. #   </entry>
  457. # </feed>
  458. #
  459. #
  460. Param(
  461.    [Parameter(Mandatory = $true, Position = 0)]
  462.    [System.Xml.Linq.XName]$root
  463. ,
  464.    [Parameter(Mandatory = $false)]
  465.    [string]$Version = "1.0"
  466. ,
  467.    [Parameter(Mandatory = $false)]
  468.    [string]$Encoding = "UTF-8"
  469. ,
  470.    [Parameter(Mandatory = $false)]
  471.    [string]$Standalone = "yes"
  472. ,
  473.    [Parameter(Position=99, Mandatory = $false, ValueFromRemainingArguments=$true)]
  474.    [PSObject[]]$args
  475. )
  476. BEGIN {
  477.    if(![string]::IsNullOrEmpty( $root.NamespaceName )) {
  478.       Function New-QualifiedXElement {
  479.          Param([System.Xml.Linq.XName]$tag)
  480.          if([string]::IsNullOrEmpty( $tag.NamespaceName )) {
  481.             $tag = $($root.Namespace) + $tag
  482.          }
  483.          New-XElement $tag @args
  484.       }
  485.       Set-Alias xe New-QualifiedXElement
  486.    }
  487. }
  488. PROCESS {
  489.    #New-Object XDocument (New-Object XDeclaration "1.0", "UTF-8", "yes"),(
  490.    New-Object XDocument (New-Object XDeclaration $Version, $Encoding, $standalone),(
  491.       New-Object XElement $(
  492.          $root
  493.          while($args) {
  494.             $attrib, $value, $args = $args
  495.             if($attrib -is [ScriptBlock]) {
  496.                &$attrib
  497.             } elseif ( $value -is [ScriptBlock] -and "-Content".StartsWith($attrib)) {
  498.                &$value
  499.             } elseif ( $value -is [XNamespace]) {
  500.                New-XAttribute ([XNamespace]::Xmlns + $attrib.TrimStart("-")) $value
  501.             } else {
  502.                New-XAttribute $attrib.TrimStart("-") $value
  503.             }
  504.          }
  505.       ))
  506. }
  507. END {
  508.    Set-Alias xe New-XElement
  509. }
  510. }
  511.  
  512. Set-Alias xml New-XDocument -Option AllScope
  513. Set-Alias New-Xml New-XDocument -Option AllScope
  514.  
  515. function New-XAttribute {
  516. #.Synopsys
  517. #       Creates a new XAttribute (an xml attribute on an XElement for XDocument)
  518. #.Description
  519. #  This is the work-horse for the XML mini-dsl
  520. #.Parameter name
  521. #       The attribute name
  522. #.Parameter value
  523. #  The attribute value
  524. Param([Parameter(Mandatory=$true)]$name,[Parameter(Mandatory=$true)]$value)
  525.    New-Object XAttribute $name,$value
  526. }
  527. Set-Alias xa New-XAttribute -Option AllScope
  528. Set-Alias New-XmlAttribute New-XAttribute -Option AllScope
  529.  
  530.  
  531. function New-XElement {
  532. #.Synopsys
  533. #       Creates a new XElement (an xml tag for XDocument)
  534. #.Description
  535. #  This is the work-horse for the XML mini-dsl
  536. #.Parameter tag
  537. #       The name of the xml tag
  538. #.Parameter args
  539. #       this is where all the dsl magic happens. Please see the Examples. :)
  540. Param(
  541.    [Parameter(Mandatory = $true, Position = 0)]
  542.    [System.Xml.Linq.XName]$tag
  543. ,
  544.    [Parameter(Position=99, Mandatory = $false, ValueFromRemainingArguments=$true)]
  545.    [PSObject[]]$args
  546. )
  547.   Write-Verbose $($args | %{ $_ | Out-String } | Out-String)
  548.   New-Object XElement $(
  549.      $tag
  550.      while($args) {
  551.         $attrib, $value, $args = $args
  552.         if($attrib -is [ScriptBlock]) {
  553.            &$attrib
  554.         } elseif ( $value -is [ScriptBlock] -and "-Content".StartsWith($attrib)) {
  555.            &$value
  556.         } elseif ( $value -is [XNamespace]) {
  557.             New-XAttribute ([XNamespace]::Xmlns + $attrib.TrimStart("-")),$value
  558.         } else {
  559.            New-XAttribute $attrib.TrimStart("-"), $value
  560.         }
  561.      }
  562.    )
  563. }
  564. Set-Alias xe New-XElement -Option AllScope
  565. Set-Alias New-XmlElement New-XElement -Option AllScope
  566.  
  567. Export-ModuleMember -function New-XDocument, New-XAttribute, New-XElement, Remove-XmlNamespace, Convert-Xml, Select-Xml, Format-Xml -alias *

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