6
Feb
by Chris
There is no reason why a Translet shouldn't use XQuery as opposed to Xslt. So here is one that will transform a DAXml into a Windows Play List (WPL) using XQuery. It is quite simple
function T-DAXmlToWpl{
param ($inxml)
begin{
Add-Type -path "PSLib:\xml\xquery\querymachine\QueryMachine.XQuery.dll"
$xq = @'
(:<?wpl version="1.0"?>:)
<smil>
<head>
<meta name="Generator" content="Powershell Translet T-Dax2Wpl"/>
<author>Chris Bayes</author>
<title>Playlist</title>
</head>
<body>
<seq>
{
for $f in //file
return
<media src="{$f/@FullName}" />
}
</seq>
</body>
</smil>
'@
}
process{
if ($_ -is [xml]){
$xqresult = [DataEngine.XQuery.XPathFactory]::QuerySingleNode($_, $xq)
$xqresult.OuterXml
}
}
end{
if ($inxml -is [xml]){
$xqresult = [DataEngine.XQuery.XPathFactory]::QuerySingleNode($inxml, $xq)
$xqresult.OuterXml
}
}
}
I am using OuterXml here because the result of the query is a single XmlElement (<smil>). The result of this translet would usually be written to a file with the Set-Content commandlet so it is ok to pass a string down the pipeline. If an [xml] object is required then [xml]($xqresult.OuterXml) can be used instead. I will have to do some timings to see if importing $xqresult into a new emty [xml] object is quicker than casting to an [xml] object.
It can be used like this
PS> . .\T-DAXmlToWpl.ps1
PS> Get-DirAsXml ..\test -props=@{FullName=""} | T-DAXmlToWpl | sc playlist.wpl
After a bit of testing I changed the XQuery to
$xq = @'
(:<?wpl version="1.0"?>:)
document{
<smil>
<head>
<meta name="Generator" content="Powershell Translet T-Dax2Wpl"/>
<author>Chris Bayes</author>
<title>Playlist</title>
</head>
<body>
<seq>
{
for $f in //file
return
<media src="{$f/@FullName}" />
}
</seq>
</body>
</smil>
}
'@
and QuerySingleNode returns an XmlDocument :-) however it has a <?xml version="1.0" encoding="utf-8"?> xml declaration which is not part of the SMIL spec but Windows Media Player doesn't seem to mind.
I then tried
function T-DAXmlToWpl{
param ($inxml)
begin{
Add-Type -path "PSLib:\xml\xquery\querymachine\QueryMachine.XQuery.dll"
$xq = @'
document{
<?wpl version="1.0"?>,<smil>
<head>
<meta name="Generator" content="Powershell Translet T-DAXmlToWpl"/>
<author>Chris Bayes</author>
<title>Playlist</title>
</head>
<body>
<seq>
{
for $f in //file[@Extension=".mp3"]
return
<media src="{$f/@FullName}" />
}
</seq>
</body>
</smil>
}
'@
}
process{
if ($_ -is [xml]){
[DataEngine.XQuery.XPathFactory]::QuerySingleNode($_, $xq)
}
}
end{
if ($inxml -is [xml]){
[DataEngine.XQuery.XPathFactory]::QuerySingleNode($inxml, $xq)
}
}
}
which produces something like this
<?xml version="1.0" encoding="utf-8"?>
<?wpl version="1.0"?>
<smil>
<head>
<meta name="Generator" content="Powershell Translet T-DAXmlToWpl" />
<author>Chris Bayes</author>
<title>Playlist</title>
</head>
<body>
<seq>
<media src="D:\music\Culture - Two Sevens Clash (30th Anniversary Ed.) TQMP\04_Culture - Two Sevens Clash.mp3" />
...
</seq>
</body>
</smil>
which has the xml declaration and the wpl processing instruction which Windows Media Player also plays so I will leave it like that.
Because we are producing an XmlDocument we need to use the Format-Xml commandlet before we can use the Set-Content commandlet, something like this
PS> Get-DirAsXml D:\music -props @{FullName="";Extension=""} | T-DAXmlToWpl | Format-Xml | Set-Content allplaylist.wpl
