<<  February 2017  >>

View posts in large calendar



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
I recently spotted Standalone XQuery Implementation in .NET on Codeplex and decided to integrate it with DAXml explorer. I'm going to start with a previous post and add a few things. A ToolBar to switch to XQuery search and run the XQuery <ToolBarTray Background="White" Grid.Row="0">     <ToolBar Band="1" BandIndex="0">         <Button Name="SEARCHTOOL">             <TextBlock>Search</TextBlock>         </Button>         <Button Name="RUNTOOL">             <TextBlock>Run</TextBlock>         </Button>     </ToolBar>     <ToolBar Band="1" BandIndex="1" Visibility="{Binding ElementName=TABCONTROL, Path=Visibility}">         <TextBlock FontSize="20"> A </TextBlock>         <Slider Name="TEXTSIZE" Maximum="50" Width="100" Value="12" Orientation="Horizontal" HorizontalAlignment="Left" AutoToolTipPlacement="BottomRight" AutoToolTipPrecision="2" />     </ToolBar> </ToolBarTray> and a TabControl to switch between the XQuery and the results <TabControl Name="TABCONTROL" Grid.Column="2" Grid.Row="1" Visibility="Hidden">     <TabItem Name="TABXQUERY" Header="XQuery">         <TabItem.Content>             <TextBox Name="TABQUERYSOURCE" AcceptsReturn="True" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" FontSize="{Binding ElementName=TEXTSIZE, Path=Value}" />         </TabItem.Content>     </TabItem>     <TabItem Name="XQUERYRESULT" Header="Result">         <TabItem.Content>             <ListView Name="LISTVIEW2" Grid.Column="2" Grid.Row="1" HorizontalAlignment="Stretch" Visibility="Visible">                 <ListView.View>                     <GridView AllowsColumnReorder="true" ColumnHeaderContainerStyle="{DynamicResource CustomHeaderStyle}">                         <GridViewColumn Header="Name" CellTemplate="{StaticResource ItemTemplate}">                         </GridViewColumn>                     </GridView>                 </ListView.View>             </ListView>         </TabItem.Content>     </TabItem> </TabControl> We need a couple of events wired up $SEARCHTOOL.add_Click({     if ($TABCONTROL.Visibility -eq [System.Windows.Visibility]::Visible){         $TABCONTROL.Visibility = [System.Windows.Visibility]::Hidden         $LISTVIEW.Visibility = [System.Windows.Visibility]::Visible     }else{         $TABCONTROL.Visibility = [System.Windows.Visibility]::Visible         $LISTVIEW.Visibility = [System.Windows.Visibility]::Hidden     } }) that will switch from normal to search view. And an event to do the XQuery on the DAXml $RUNTOOL.add_Click({     Add-Type -path "D:\QueryMachine.XQuery.1.3\QueryMachine.XQuery.1.3\QueryMachine.XQuery.dll"     $xqresult = [DataEngine.XQuery.XPathFactory]::QueryNodes($xml, $TABQUERYSOURCE.Text)     $LISTVIEW2.ItemsSource = $xqresult     $TABXQUERYRESULT.IsSelected = $true }) This might be displayed like this Normal explorer view. XQuery search view. XQuery result view. It can be used like this Xaml-DisplayDirExp (get-dirasxml ..\test -props @{Length="";LastWriteTime="";Extension="";FullName=""} ) or like this Xaml-DisplayDirExp (get-dirasxml ..\test -CustomProps {     param ($element, $directory, $file, $prefix, $namespace)     try{         [xml]$xmp = (pslib:\xml\ReadingXMP.exe $file.FullName)         $xmpr = $xmp.SelectSingleNode("/*")         $inode = $element.OwnerDocument.ImportNode($xmpr, $true)         [void]$element.AppendChild($inode)     }catch{} } -props @{Length="";LastWriteTime="";Extension="";FullName=""} ) which will use the ReadingXMP from this previous post to stuff XMP RDF from JPG files into the DAXml. Depending on which method you use will depend on the XQuery you use. With DAXml stuffing you can use an XQuery like this declare namespace MPReg=""; for $a in //file[@Extension=".jpg"][//MPReg:PersonDisplayName = "Chris Bayes"] order by $a/@Length return $a and if you use sidecar files then you can use XQuery like this declare namespace MPReg=""; for $a in //file[@Extension=".jpg"] where doc(concat(@FullName, ".xmp"))//MPReg:PersonDisplayName = "Chris Bayes" order by $a/@Length return $a either way the XQuery will return all JPG files in all your folders where 'Chris Bayes' is in the MPReg:PersonDisplayName of the XMP RDF ordered by the file size. If you used order by $a//exif:GPSLatitude you would get all JPG files in all your folders where 'Chris Bayes' is in the MPReg:PersonDisplayName of the XMP RDF ordered by the e/w distance from the Greenwich Meridian. Here is the code