basex-lsp/webapp/lsp-manager/lib.xq/outlet.xqm
2025-10-13 23:07:01 +01:00

102 lines
No EOL
3.6 KiB
Text

xquery version '3.1';
(:~ save conversion outputs to file
ensures target folders created
save multiple docs when root <wrapper> found
optionally serialize XML with default namespace
@author quodatum Andy Bunce
:)
module namespace outlet = 'urn:conversion:outlet';
(: serialization options
key is arbitary name, value is BaseX serialization option map
for xml serializations the non-standard 'ns' option supplies a namespace to use as default ' :)
declare variable $outlet:serial:=map{
"xvrl": map{"method":"xml","ns":"http://www.xproc.org/ns/xvrl"},
"docbook":map{"method":"xml","ns":"http://docbook.org/ns/docbook"},
"csv": map{"method":"text"},
"xml": map{"method":"xml"}
};
(:~save $doc to $dest unless empty,will create directories as required
@param $opts serialization options and ns to set a default namespace :)
declare function outlet:save($doc as item(),$dest as xs:string?,$opts as map(*)?)
as xs:string?{
if (exists($dest))
then
let $doc:=if($opts?ns)
then outlet:change-element-ns-deep($doc,$opts?ns,"")
else $doc
return (
file:create-dir(file:parent($dest)),
file:write($dest,$doc,map:remove($opts,"ns")),
$dest
)
};
(:~ save file or files if node is wrapper
@return paths to saved files
:)
declare function outlet:save-wrapper($doc as item(),$dest as xs:string?,$opts as map(*)?)
as xs:string*{
if ($doc/wrapper)
then $doc/wrapper/result! outlet:save(*,file:resolve-path(@href,$dest),$opts)
else outlet:save($doc,$dest,$opts)
};
(:~ from functx http://www.xqueryfunctions.com/xq/functx_change-element-ns-deep.html :)
declare function outlet:change-element-ns-deep
( $nodes as node()* ,
$newns as xs:string ,
$prefix as xs:string ) as node()* {
for $node in $nodes
return if ($node instance of element())
then (element
{QName ($newns,
concat($prefix,
if ($prefix = '')
then ''
else ':',
local-name($node)))}
{$node/@*,
outlet:change-element-ns-deep($node/node(),
$newns, $prefix)})
else if ($node instance of document-node())
then outlet:change-element-ns-deep($node/node(),
$newns, $prefix)
else $node
} ;
(:~ @see https://stackoverflow.com/a/8600987/3210344 :)
declare function outlet:remove-prefixes($node as node(), $prefixes as xs:string*)
as node(){
typeswitch ($node)
case element()
return
if ($prefixes = ('#all', prefix-from-QName(node-name($node)))) then
element {QName(namespace-uri($node), local-name($node))} {
$node/@*,
$node/node()/outlet:remove-prefixes(., $prefixes)
}
else
element {node-name($node)} {
$node/@*,
$node/node()/outlet:remove-prefixes(., $prefixes)
}
case document-node()
return
document {
$node/node()/outlet:remove-prefixes(., $prefixes)
}
default
return $node
};
(:~ relative file paths below folder $path, matching $selector :)
declare function outlet:select($path as xs:string,$selector as map(xs:string,item()*))
as xs:string*
{
file:list($path,true(),$selector?pattern)
[some $i in $selector?include satisfies contains(.,$i)]
[every $x in $selector?exclude satisfies not(contains(.,$x))]
};