<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Frontier at Work</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/frontier_at_work/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/frontier_at_work/feed.xml</link>
    <description>It&amp;#039;s just another frontier where you seek out new technologies ...</description>
    <lastBuildDate>Wed, 17 Apr 2019 04:10:49 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>PowerShellのバイナリモジュールをF#で書こう！</title>
      <link>https://docs.microsoft.com/archive/blogs/frontier_at_work/powershellf</link>
      <pubDate>Thu, 04 Dec 2014 07:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Ichiro Ota (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/frontier_at_work/2014/12/04/powershellf/</guid>
      <description><![CDATA[この記事はPowerShell Advent Calendar...]]></description>
      <content:encoded><![CDATA[<p><span lang="ja">この記事は</span><span lang="en-US">PowerShell Advent Calendar 2014</span><span lang="ja">の</span><span lang="en-US">5</span><span lang="ja">日めの記事です。</span></p>
<p><span lang="en-US">F#</span><span lang="ja">の文法は非常に簡潔で、短いタイプ量でコードを記述できるようになっています。このため、いったん</span><span lang="en-US">F#</span><span lang="ja">のコーディングになれてしまうと</span><span lang="en-US">C#</span><span lang="ja">でのコーディングが少し億劫になってしまいがちです（異論は認めません）。</span><span lang="en-US">PowerShell</span><span lang="ja">用にバイナリーモジュールを書くときも同様です。できれば</span><span lang="en-US">F#</span><span lang="ja">で書きたい！</span></p>
<p><span lang="ja">バイナリモジュールを</span><span lang="en-US">F#</span><span lang="ja">で書くことそのもはそれほどむつかしくありません。</span><span lang="en-US">C#</span><span lang="ja">で書くときと同じように</span><span lang="en-US">PSCmdlet</span><span lang="ja">を継承したクラスを定義してアセンブリを生成するだけです（</span><span lang="en-US">C#</span><span lang="ja">によるバイナリモジュールの生成の詳細については、ぎたぱそ先生の「</span><a href="https://tech.guitarrapc.com/entry/2013/12/03/014013"><span lang="ja">PowerShell のモジュール詳解とモジュールへのコマンドレット配置手法を考える</span></a><span lang="ja">」をご覧ください）。</span></p>
<p><span lang="ja">以下は、パイプラインを通じて与えられた整数の中から最大値を返すコマンドレット</span><span lang="en-US">Select-Max</span><span lang="ja">を</span><span lang="en-US">F#</span><span lang="ja">で定義した例です。</span></p>
<pre>    namespace sample
    open System.Management.Automation

    [&lt;Cmdlet("Select", "Max")&gt;]
    type SelectMax() = 
        inherit PSCmdlet()
        [&lt;DefaultValue&gt;]
        val mutable private result : int
        [&lt;DefaultValue&gt;]
        val mutable private _InputValue : int
        [&lt;Parameter(Mandatory=false,ValueFromPipeline=true)&gt;]
        member public this.InputValue
            with get() = this._InputValue
            and set value = this._InputValue &lt;- value
        override this.BeginProcessing() =
            do this.result &lt;- 0
        override this.ProcessRecord() =
            do this.result &lt;- max this.result this._InputValue
        override this.EndProcessing() =
            do base.WriteObject(this.result)
</pre>
<p><span lang="ja">この</span><span lang="en-US">F#</span><span lang="ja">のソースファイルをバイナリモジュールとして利用するには、まずコンパイルし、生成されたアセンブリを</span><span lang="en-US">Import-Module</span><span lang="ja">で読みこんでやる必要があります。以下はコマンドラインコンパイラ</span><span lang="en-US">fsc.exe</span><span lang="ja">を利用してコンパイルしている例です。</span></p>
<pre>    fsc.exe --out:sample.dll --target:library `<br />        --reference:System.Management.Automation sample.fs
    Import-Module .\sample.dll
</pre>
<p><span lang="ja">これで以下のように</span><span lang="en-US">F#</span><span lang="ja">のソースファイルに記述したコマンドレットを利用できます。</span></p>
<pre>    PS C:\&gt; @(1,2,3) | Select-Max
    3
</pre>
<p><span lang="ja">さて、これで一応使えるのですが、fsc.exeでわざわざコンパイルするのが少し面倒です。特に</span><span lang="en-US">fsc.exe</span><span lang="ja">には標準でパスが通っていないので、上記のように普通に</span><span lang="en-US">fsc.exe</span><span lang="ja">とだけ入力するだけでは通常エラーになりますし、出来上がったモジュールを配布する時のことを考えると、環境変数</span><span lang="en-US">PATH</span><span lang="ja">の設定をしてもらうのも少し億劫です（<span lang="en-US">F#</span><span lang="ja">を利用していない人にとっては</span><span lang="en-US">fsc.exe</span><span lang="ja">をインストールするのがそもそも億劫なのでは、といった疑問は思っても口には出さない</span>）。</span></p>
<p><strong><span lang="en-US">F#</span><span lang="ja">のソースファイルをモジュールのようにあつかう</span></strong></p>
<p><span lang="ja">そこで</span><span lang="en-US">F#</span><span lang="ja">のソースファイル、上記の例でいえば</span><span lang="en-US">sample.fs</span><span lang="ja">ですが、これをあたかもモジュールのように扱うことはできないでしょうか。例えば以下のようにです。</span></p>
<pre>    Import-Module sample.fs</pre>
<p><span lang="ja">さすがにいろいろな制約があって、これはそのままに実現するのはちょっとむつかしいのですが、これにかなり近い形なら可能です。今回ここで紹介する</span><span lang="en-US">PowerShell</span><span lang="ja">モジュール</span><span lang="en-US">FSharp</span><span lang="ja">を用いると、以下のような形で</span><span lang="en-US">F#</span><span lang="ja">のソースをモジュールとしてロードできるようになります。</span></p>
<pre>    Import FSharp<br />    New-FsModule sample.fs | Import-Module
</pre>
<p><span lang="en-US">New-FsModule</span><span lang="ja">でまずモジュールを生成し、それを</span><span lang="en-US">Import-Module</span><span lang="ja">で読みこむという二段階の処理になっていますが、</span><span lang="en-US">fsc.exe</span><span lang="ja">でコンパイルして&hellip;&hellip;という手順と比較すればかなり手軽に使えるのではないでしょうか。</span></p>
<p lang="ja"><strong>実装の概要</strong></p>
<p><span lang="ja">興味のある方もいるかもしれませんので、念のため</span><span lang="en-US">FSharp</span><span lang="ja">の概要についも簡単に触れておきましょう。</span><span lang="ja"><a title="https://github.com/ichiohta/PSFsharp/blob/master/FSharp/FSharp.psm1" href="https://github.com/ichiohta/PSFsharp/blob/master/FSharp/FSharp.psm1">ソース</a>を見てわかるように、このモジュールでは以下の</span><span lang="en-US">3</span><span lang="ja">つの関数が定義されています。</span></p>
<table border="1">
<tbody>
<tr>
<td width="30%">Find-FscExe</td>
<td><span lang="en-US">fsc.exe</span><span lang="ja">がインストールされている場所をレジストリから探し出す</span>&nbsp;</td>
</tr>
<tr>
<td nowrap="nowrap">Invoke-FscExe&nbsp;</td>
<td><span lang="en-US">Find-FscExe</span><span lang="ja">を用いて発見したf</span><span lang="en-US">sc.exe</span><span lang="ja">を起動します</span></td>
</tr>
<tr>
<td>New-FsModule</td>
<td><span lang="ja">指定された</span><span lang="en-US">F#</span><span lang="ja">のソースファイルを</span><span lang="en-US">Find-FscExe</span><span lang="ja">を用いてコンパイルし、生成されたアセンブリへのパスを返します</span></td>
</tr>
</tbody>
</table>
<p><span lang="ja">解説が必要な箇所はほとんどないかと思います。</span><span lang="en-US">Find-FsxExe</span><span lang="ja">のロジックがいくぶんアドホックに見えますが、こちらは</span><span lang="en-US">FSharp.Compiler.CodeDom</span><span lang="ja">パッケージの</span><a href="https://github.com/fsprojects/FSharp.Compiler.CodeDom/blob/master/src/FSharp.Compiler.CodeDom/CompilerLocationUtils.fs"><span lang="en-US">CompilerLocationUtil.fs</span></a><span lang="ja">を参考にしています。</span></p>
<p lang="ja"><span style="color: #ff0000;"><strong><span lang="en-US">NOTE:</span></strong></span><span lang="ja">サンプルを含めたソースファイル一式は</span><a href="https://github.com/ichiohta/PSFsharp"><span lang="en-US">github</span></a><span lang="ja">から入手可能です。</span></p>
<p>&nbsp;</p>
<p><span lang="ja"><br /></span></p>]]></content:encoded>
    </item>
    <item>
      <title>パイプラインのオブジェクトをのぞき見する</title>
      <link>https://docs.microsoft.com/archive/blogs/frontier_at_work/33</link>
      <pubDate>Wed, 05 Mar 2014 18:25:00 GMT</pubDate>
      <dc:creator><![CDATA[Ichiro Ota (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/frontier_at_work/2014/03/05/33/</guid>
      <description><![CDATA[まずはスクリプトそのものから。
function Watch-PipeLine {  param (    [Parameter(Mandatory=$true)]    [ScriptBlock]...]]></description>
      <content:encoded><![CDATA[<p>まずはスクリプトそのものから。</p>
<pre style="padding-left: 30px;">function Watch-PipeLine {<br /><br />  param (<br />    [Parameter(Mandatory=$true)]<br />    [ScriptBlock] $ScriptBlock,<br />    [Parameter(Mandatory=$true,ValueFromPipeLine=$true)]<br />    [PSObject] $Object<br />  )<br /><br />  process {<br />    $Object | Foreach $ScriptBlock<br />    $Object<br />  }<br /><br />}<br /><br />New-Alias Watch Watch-PipeLine&nbsp;</pre>
<p>これを使うと、パイプラインを流れるオブジェクトを簡単にのぞき見できます。たとえば以下のようなファイル名の一覧を取得している処理があったとしましょう。</p>
<pre style="padding-left: 30px;">$logFiles = dir -Recurse Logs |<br /> Where PSIsContainer -eq $false |<br /> Foreach Name |<br /> Sort-Object</pre>
<p>ここでファイルサイズを合計もとりたいという要望があったので、以下のように書き換えたとします。</p>
<pre style="padding-left: 30px;">$total = 0<br /><br />$logFiles = dir -Recurse Logs |<br /> Where PSIsContainer -eq $false |<br /> Foreach {<br />   $total += $_.Length<br />   $_.Name<br /> } |<br /> Sort-Object</pre>
<p>これで問題はまったくないのですが、パイプラインの流れがちょっとみづらくなりました。Foreach のところで最終的に $_.Name を emit していることが読み取りやすいかどうかがポイントです。ここで、上記の Watch-PipeLine を用いると、以下のように書き換えることができます。</p>
<pre style="padding-left: 30px;">$total = 0<br /><br />$logFiles = dir -Recurse Logs |<br /> Where PSIsContainer -eq $false |<br /> Watch { $total += $_.Length } |<br /> Foreach Name |<br /> Sort-Object</pre>
<p>パイプラインの各段の処理にはまったく手をいれておらず、Watch の一行を追加しただけです。Watch はパイプラインの値をのぞき見して何か処理をしている、ということがわかっているので、パイプラインのメインの流れをみるうえでは Watch の部分を気にする必要はありません。</p>
<p>実のところ、ここで用いた Watch は以下のような Foreach &nbsp;と等価です。</p>
<pre style="padding-left: 30px;">Foreach { $total += $_.Length; $_ }</pre>
<p>これで十分なのでは、という話もあるんですが、これはこれで最後の $_ を付け忘れたりすることがあります。</p>
<p>というか付け忘れたので、こういう案をひとつ思いついた、というエントリでした。</p>]]></content:encoded>
    </item>
    <item>
      <title>New-Module を用いてカスタムオブジェクトを生成する</title>
      <link>https://docs.microsoft.com/archive/blogs/frontier_at_work/new-module</link>
      <pubDate>Sat, 21 Dec 2013 07:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Ichiro Ota (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/frontier_at_work/2013/12/21/new-module/</guid>
      <description><![CDATA[PowerShell でカスタムオブジェクトを定義する一番ストレートな方法はハッシュテーブルと Add-Member を組み合わせるパターンでしょう。
$custom =...]]></description>
      <content:encoded><![CDATA[<p>PowerShell でカスタムオブジェクトを定義する一番ストレートな方法はハッシュテーブルと Add-Member を組み合わせるパターンでしょう。</p>
<p style="padding-left: 30px;">$custom = [pscustomobject] @{&nbsp;Message = 'Hello, world!'&nbsp;} |<br />&nbsp; Add-Member -PassThru -MemberType ScriptMethod -Name Hello -Value {<br />&nbsp;&nbsp;&nbsp; Write-Host -Foreground Green $this.Message<br />&nbsp; }</p>
<p>この例は、Message というプロパティと、その値をホストに緑色で表示する Hello というメソッドをもったカスタムオブジェクトを定義しています。少し複雑な処理をするときなどは、このようなカスタムオブジェクトを積極的に活用する機会が多くなりますが、いかんせん記述が煩雑なことに加えて、メンバーのスコープを制御できないという欠点があります。</p>
<p>そんな場合は、動的モジュールを利用してカスタムオブジェクトを定義するといいですよ、というのが今回のネタです。</p>
<p><span lang="ja">動的モジュールとは、その名のとおり、メモリ空間内に動的に生成されるモジュールのことで、</span><span lang="en-US">New-Module </span><span lang="ja">を用いて生成します。試しに、動的モジュールをひとつ定義してみましょう。</span></p>
<p style="padding-left: 30px;">New-Module {<br />&nbsp; $Message = 'Hello, world!'<br />&nbsp; function Hello { Write-Host -Foreground Green $Message }<br />}</p>
<p>これを実行するとモジュールが動的に生成され、モジュール内で定義したメンバーがセッションにインポートされ、利用可能になります。</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/57/27/2746.Fig1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-57-27/2746.Fig1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/57/27/2746.Fig1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-57-27/2746.Fig1.png" alt="" border="0" /></a></p>
<p>これだけだと動的にモジュールを定義できました、というだけの話であまり面白くありません。興味深くなるのは New-Module に -AsCustomObject オプションを指定してからです。</p>
<p style="padding-left: 30px;">$custom = New-Module&nbsp; {<br />&nbsp;&nbsp; &hellip;<br />} -AsCustomObject</p>
<p>このオプションを指定すると、エクスポートしたモジュールメンバーは現在のセッションのスコープにインポートされなくなります。そのかわり、モジュールのオブジェクトのメンバーとしてアクセスできるようになります。</p>
<p style="padding-left: 30px;">$custom.Hello()</p>
<p>ここで気づかれたかと思いますが、このように生成した動的モジュールのインスタンスの振る舞いはカスタムオブジェクトそのものです。しかも、Export-ModuleMember を利用することで、メンバー変数や関数のスコープを自由にコントロールできるという利点があります。たとえば、モジュールで定義した変数は、デフォルトではエクスポートされません（上記の例でいうと$Messageという変数）。エクスポートさせるには以下のように明示的に指示する必要があります。</p>
<p style="padding-left: 30px;">$custom = New-Module&nbsp; {<br />&nbsp;&nbsp; &hellip;<br />&nbsp; Export-ModuleMember -Function Hello<br />&nbsp; Export-ModuleMember -Variable Message<br /><br />} -AsCustomObject</p>
<p>Export-ModuleMember を用いて明示的に Message をエクスポートしていることに加え、先ほどは暗黙的にエクスポートされていた Hello も明示的にエクスポートしている点に注意してください。明示的なエクスポートを用いる場合、公開したいメンバーを明示的にすべてエクスポートする必要があります。</p>
<p>モジュール定義にもちいるスクリプトブロックは、scriptblockのインスタンスであることには変わりないので、paramを用いて引数をとることができます。これを利用すると、以下のようなコンストラクター的関数を定義することも可能です。</p>
<p style="padding-left: 30px;">function New-Greeter {<br />&nbsp; param ([string] $ToWhom = 'World')<br />&nbsp; New-Module {<br />&nbsp;&nbsp;&nbsp; param ([string] $ToWhom)<br />&nbsp;&nbsp;&nbsp;&nbsp;$Message = "Hello, $ToWhom!"<br />&nbsp;&nbsp;&nbsp; Function Hello { Write-Host -Foreground Green $Message }<br />&nbsp; } -AsCustomObject -ArgumentList $ToWhom<br />}</p>
<p>というわけで、New-Module を用いたカスタムオブジェクトの定義方法について簡単にまとめてみました。大規模なスクリプトを書くときにカスタムオブジェクトは非常に有用なので、ぜひ利用を検討してみてください。</p>
<p>明日は&nbsp;&alpha;&epsilon;&tau;&omicron;&sigmaf; さんの担当です。お楽しみに！&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>XDocument を用いて XML を処理する</title>
      <link>https://docs.microsoft.com/archive/blogs/frontier_at_work/xdocument-xml</link>
      <pubDate>Mon, 17 Dec 2012 21:22:00 GMT</pubDate>
      <dc:creator><![CDATA[Ichiro Ota (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/frontier_at_work/2012/12/17/xdocument-xml/</guid>
      <description><![CDATA[スクリプトを書いていると、たびたび XML のファイルを作成したり、あるいは変更したりする機会があります。例えば、XML...]]></description>
      <content:encoded><![CDATA[<p>スクリプトを書いていると、たびたび XML のファイルを作成したり、あるいは変更したりする機会があります。例えば、XML 形式の設定ファイルを自動生成したり、その設定ファイルを更新するようなケースです。</p>
<p>PowerShell で標準で用意されている XML のサポートは、DOM をベースにした XmlDocument クラスを用いるものです。当然ながら、この仕組みを用いてスクリプトを書くことに全然問題はありません。</p>
<p>しかし、シンプルかつよりスマートな System.XML.Linq が使える現在、PowerShell ベースとはいえ今更 DOM ベースの XmlDocument を使うのは、少し心理的に抵抗がある人もいるでしょう（例えば筆者）。XmlDocument と XDocument で、機能的に大きな違いはないのですが、XML 標準の DOM という考え方には幾分クセがあり、XmlDocument のその独特の使用方法に馴染むまで少しムズムズする可能性があります（ちなみに私は10年来ずっとムズムズしたままです）。</p>
<p>そういうわけで、XDocument を手軽に扱うための PowerShell モジュールを作ってみました（最後にソースを貼り付けてあります）、というのが今回のお題です。基本的にはコンストラクターをラップしたコマンドレットが中心で、以下のような形で使うことを想定しています。</p>
<blockquote>
<p>$doc = New-XDocument ( ` <br />&nbsp; New-XElement users ` <br />&nbsp;&nbsp;&nbsp; (New-XElement user (New-XAttribute name ichiro)) ` <br />&nbsp;&nbsp;&nbsp; (New-XElement user (New-XAttribute name andrej)) ` <br />)</p>
</blockquote>
<p>これは新規に以下のような XML 文書のオブジェクトである XDocument を生成しています。</p>
<blockquote>
<p>&lt;?xml version='1.0'? encoding='utf-8'&gt; <br />&lt;users&gt; <br />&nbsp; &lt;user name='ichiro' /&gt; <br />&nbsp; &lt;user name='andrej' /&gt; <br />&lt;/users&gt;</p>
</blockquote>
<p>さすがにこれだとちょっとタイプ量が半端ないので、alias も仕込んでみました。これで以下のようにスッキリと書けます。</p>
<blockquote>
<p>$doc = xd (xe users (xe user (xa name ichiro)) (xe user (xa name andrej)))</p>
</blockquote>
<p>ユーザーを追加してみましょう。XPath を使って users のノードを取り出し、そのノードに新しい user ノードを子供として追加します。</p>
<blockquote>
<p>$users = $doc | Select-XNode users <br />$users.Add((xe user (xa name taro)))</p>
</blockquote>
<p>Select-XNode は [System.Xml.Linq.Extensions]::XPathEvaluate のラッパーです。ただそのままラップすると芸が無いので、PowerShell っぽく引数をパイプラインから取れるように細工しています。</p>
<p>ファイルへの保存およびファイルからの読み出しも用意してあります。</p>
<blockquote>
<p>$doc | Set-XDocument .\users.xml&nbsp; <br />$doc = Get=XDocument .\users.xml</p>
</blockquote>
<p>さて、生成したり、変更したり、といった観点で XDocument は非常に使い勝手がいいのですが、XmlDocument の使い勝手のほうが遥かによい場合があります。これは PowerShell 限定の話なのですが、PSObject として XmlDocument がラップされる際、属性や子供の要素の値を簡単にアクセスできるように、属性や子供の要素の名前のプロパティが自動で生成されます。例えば、さきほどのユーザーリストの XML 文書、ユーザーの名前を取り出したい場合、XmlDocument だと以下のように直感的にかけます。</p>
<blockquote>
<p>[xml] $doc = Get-Content .\users.xml&nbsp; <br /> $names = @($doc.users.user | Foreach { $_.name })</p>
</blockquote>
<p>最初、これと同じことを XDocument で出来るといいかなぁ、と思い、生成した XDocument / XElement に NoteProperty を後からくっつける&hellip;&hellip;ようなことをちょっと考えていたんですが、ちょいと面倒、というか不毛な感じがしてきたのでやめました。</p>
<p>代わりに、もっと簡単な方法ですが、XmlDocument と XDocument を相互変換できるようにしてみました。利用シーンに応じて適切に使い分けるといいでしょう。</p>
<blockquote>
<p>$doc = xd (xe users (xa version 1) (xe user (xa name ichiro)) (xe user (xa name andrej))) | <br />&nbsp; ConvertFrom-XDocument</p>
</blockquote>
<blockquote>
<p>$names = $doc.users.user | Foreach {$_.name }</p>
</blockquote>
<p>逆に、XmlDocument を取り扱っているときに、更新の場合だけ XDocument に変更するのもありです。</p>
<p>明日は Jolly.Jive さんの番です。お楽しみに！</p>
<p>&nbsp;</p>
<h3>モジュールのソースコード</h3>
<table border="1">
<tbody>
<tr>
<td>
<pre>[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Xml")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq")

function New-XAttribute (
  [parameter(Mandatory=$true)]
  [PSObject] $Name,
  [parameter(Mandatory=$true)]
  [string] $Value
) {
  New-Object System.Xml.Linq.XAttribute @($Name, $Value)
}

function New-XElement (
  [parameter(Mandatory=$true,Position=0)]
  [string] $Name,
  [parameter(Mandatory=$false,ValueFromRemainingArguments=$true)]
  [PSObject[]] $Children = @()
) {
  $xname = [System.Xml.Linq.XName]::Get($Name)
  $element = New-Object System.Xml.Linq.XElement $xname
  $Children | Foreach { $element.Add($_) }
  $element
}

function New-XDocument (
  [parameter(Mandatory=$false,ValueFromRemainingArguments=$true)]
  [PSObject[]] $Children = @()
) {
  $doc = New-Object System.Xml.Linq.XDocument
  $Children | Foreach { $doc.Add($_) }
  $doc
}

function Select-XNode (
  [parameter(Mandatory=$true)]
  [string] $XPath,
  [parameter(Mandatory=$true,ValueFromPipeline=$true)]
  [System.Xml.Linq.XNode] $Node
) {
  process {
    [System.Xml.XPath.Extensions]::XPathEvaluate($Node, $XPath)
  }
}

function ConvertTo-XDocument (
  [parameter(Mandatory=$true,ValueFromPipeline=$true)]
  [xml] $Source
) {

  process {
    $reader = New-Object System.Xml.XmlNodeReader $Source
    try {
      [void] $reader.MoveToContent()
      [System.Xml.Linq.XDocument]::Load($reader)
    } finally {
      $reader.Close()
    }
  }
}

function ConvertFrom-XDocument (
  [parameter(Mandatory=$true,ValueFromPipeline=$true)]
  [System.Xml.Linq.XDocument] $Source
) {

  process {
    $reader = $Source.CreateReader()
    try {
      $doc = New-Object System.Xml.XmlDocument
      $doc.Load($reader)
      $doc
    } finally {
      $reader.Close()
    }
  }
}

function Get-XDocument (
  [parameter(Mandatory=$true)]
  [string] $Path,
  [parameter(Mandatory=$false)]
  [System.Text.Encoding] $Encoding = [System.Text.Encoding]::UTF8
) {

  if (-not (Test-Path $Path)) {
    throw "Unable to find '$Path'."
  }

  $Path = @(Get-ChildItem $Path)[0].FullName
  $reader = New-Object System.IO.StreamReader @($Path, $Encoding)
  
  try {
    [System.Xml.Linq.XDocument]::Load($reader)
  } finally {
    $reader.Close()
  }
}

function Set-XDocument (
  [parameter(Mandatory=$true)]
  [string] $Path,
  [parameter(Mandatory=$true,ValueFromPipeline=$true)]
  [System.Xml.Linq.XDocument] $Document
) {
  process {
    $Document.Save($Path)
  }
}

New-Alias xe New-XElement
New-Alias xa New-XAttribute
New-Alias xd New-XDocument
New-Alias sx Select-XNode

Export-ModuleMember -Function '*'
Export-ModuleMember -Alias '*'
        </pre>
</td>
</tr>
</tbody>
</table>]]></content:encoded>
    </item>
  </channel>
</rss>