Select range of elements in XQuery 3.0 - basex

I have the following xml data structure
<journey>
<leg origin='a' dest='b' />
<leg origin='b' dest='c' />
<leg origin='c' dest='d' />
<leg origin='d' dest='e' />
<leg origin='e' dest='f' />
... and so on
</journey>
I want to select leg elements from origin='b' to dest='e'
I have tried using a tumbling window, following-sibling, but can only seem to match the first and last elements with nothing in between.
I am using XQuery 3.0 in BaseX 8.6

As not all scope conditions have been given in the initial question, I am offering several answers. All of them are based on the same query prolog and the following assumptions (and probably some others):
the searched origin and destination exist
all origins & destinations occur only once
there are no cycles (e.g. b → c → b)
Query prolog
declare variable $JOURNEY :=
<journey>
<leg origin='a' dest='b' />
<leg origin='b' dest='c' />
<leg origin='c' dest='d' />
<leg origin='d' dest='e' />
<leg origin='e' dest='f' />
</journey>;
declare variable $ORIGIN := 'b';
declare variable $DEST := 'e';
Using a tumbling window
Assumption: The destination occurs after the origin.
for tumbling window $legs in $JOURNEY/leg
start $s when $s/#origin = $ORIGIN
end $e when $e/#dest = $DEST
return $legs
Using following-sibling
Assumption, same here: The destination occurs after the origin.
let $origin := $JOURNEY/leg[#origin = $ORIGIN]
let $dest := $JOURNEY/leg[#dest = $DEST]
return (
$origin,
$origin/following-sibling::leg[. << $dest],
$dest
)
Using node comparisons
Assumption, same here: The destination occurs after the origin.
let $origin := $JOURNEY/leg[#origin = $ORIGIN]
let $dest := $JOURNEY/leg[#dest = $DEST]
return $JOURNEY/leg[
. is $origin or
. >> $origin and . << $dest or
. is $dest
]
Recursive approach
Assumption: Order is not guaranteed.
declare function local:trace(
$leg as element(leg),
$journey as element(journey),
$end as xs:string
) as element(leg)* {
$leg,
for $dest in $leg/#dest[. != $end]
return local:trace($journey/leg[#origin = $dest], $journey, $end)
};
local:trace($JOURNEY/leg[#origin = $ORIGIN], $JOURNEY, $DEST)

Related

Access data (create a list) through a loop - iteration over fieldname (import from Matlab into Python)

I want to create a list from a matlab struc as follows:
#Import
mat2=sio.loadmat('TestData.mat',squeeze_me=True,struct_as_record=False)
#Solution without a loop
v1 = mat['pyDMD'].v1)
.
.
.
v17 = mat['pyDMD'].v2)
data = [v1, . . ., v17]
#Loop over fieldnames
data = []
fieldnames = []
fieldnames.append(mat['pyDMD']._fieldnames)
for t in range(len(fieldnames)):
data.append(mat['pyDMD'].fieldnames(t))
v1..v17 are a 100x100 arrays of float64. How can I iterate over fieldnames - last line. My approach is obviously not correct.
The answer is quite simple:
for field in mat2['pyDMD']._fieldnames:
snapshot = getattr(mat2['pyDMD'], field)
data.append(np.transpose(snapshot))

filepatterns to exclude a match

Shake uses various forms of matching, filepath against pattern. Is there one which can be used to exclude a pattern?
Example:
I have three directories a, b, c (somewhere in directory x) and each needs html files. There is a rule
(dir <> "//*.html") %> \out -> do -- deal with a and b
which should only deal with the directories a and b and a similar rule to process the files in c.
Is there a way (perhaps using ?>) to separate the two rules for one
(\f -> "x" prefixOf f && not "x/c" prefixOf f) <> "//*.html")
(\f -> "x/x" prefixOf f ) <> "//*.html")
and the other similarly?
The recommended approach to use xx.a.html and xx.b.html is here not possible, because files are processed with other programs which expect the regular html extension.
Alternatively
The rule:
pattern %> action
Is equivalent to:
(pattern ?==) ?> action
So you can write:
(\x -> "//*.html" ?== x && not ("c//*.html" ?== x) ?> action
To match rules matching //*.html, but not c//*.html.
More generally, there is no requirement to use the FilePattern ?== operator at all, so arbitrary matching predicates can be used instead.
With the advice (especially the hint about using **/*.html) I have it working.
The path bakedD is a prefix of staticD and the first rule deals only with files in bakedD which are not in staticD, the other only with these:
(\x -> ((bakedD <> "**/*.html") ?== x)
&& not ((staticD <> "**/*.html") ?== x)) ?> \out -> do
let md = doughD </> (makeRelative bakedD $ out -<.> "md")
runErr2action $ bakeOneFileFPs md doughD templatesD out
(staticD <> "**/*.html" ) %> \out -> do
copyFileChanged (replaceDirectory out doughD) out
There is no overlap between the two rules.
I hope this is useful for others with the same type of issue.

How to pass an array as parameter to a task with SetParameter from OmniThreadLibrary?

In Delphi XE8, I am trying to pass an array to the OTL task in SetParameter from OmniThreadLibrary:
implementation
type
TCookie = record
Name: string;
Value: string;
ExpDate: string;
ModDate: string;
end;
TCookieArray = array of TCookie;
var
CurCookies: TCookieArray;
procedure TForm1.btnStartTaskClick(Sender: TObject);
begin
SetLength(CurCookies, 2);
CurCookies[0].Name := 'username';
CurCookies[0].Value := 'Paul';
CurCookies[1].Name := 'password';
CurCookies[1].Value := 'none';
FGetCookieDetailsTask := CreateTask(GetCookieEntries, 'GetCookieEntries')
.MonitorWith(OTLMonitor)
// Compiler complaint:
.SetParameter('CookiesArray', TOmniValue.FromArray<TCookieArray>(CurCookies))
.Run;
end;
The compiler complains about the SetParameter line:
[dcc32 Error] Unit1.pas(310): E2010 Incompatible types:
'System.TArray<Unit1.TCookieArray>' and 'TCookieArray'
Unfortunately, there are no examples in the OTL book on how to use FromArray in SetParameter to pass an array to the task.
So how can this be done?
EDIT: ba__friend asked that I show the source code from my solution in the comments of his answer:
FGetCookieDetailsTask := CreateTask(GetCookieEntries, 'GetCookieEntries')
.MonitorWith(OTLMonitor)
// Now no compiler complaint:
.SetParameter('CookiesArray', CurCookies)
.Run;
procedure GetCookieEntries(const task: IOmniTask);
var
TaskCookies, HostCookies: TCookieArray;
begin
HostCookies := task.Param['CookiesArray'];
TaskCookies := Copy(HostCookies, 0, Length(HostCookies));
There are two problems in your code.
1) TCookieArray has to be declared as
TCookieArray = TArray<TCookie>;
From the compiler's standpoint, array of T and TArray<T> are (sadly) not the same thing.
2) FromArray<T> expects the type T to be the array item type, not the array type (see OtlCommon), so you have to change it from
TOmniValue.FromArray<TCookieArray>
to
TOmniValue.FromArray<TCookie>
To access this array from a task, call:
var
cookies: TCookieArray;
cookies := task.Param['CookiesArray'].ToArray<TCookie>;
Side note: This is how things should work. In OTL up to (and including) 3.04b, record type is, however, not handled correctly in ToArray<T> and FromArray<T>. A fix for that has just been committed to the GitHub.
If you want to fix your copy manually, two modifications are needed.
In TOmniValue.CastFrom<T>, this block
if ds = 0 then // complicated stuff
{$IFDEF OTL_ERTTI}
should be changed to
if ds = 0 then // complicated stuff
if ti^.Kind = tkRecord then
Result.SetAsRecord(CreateAutoDestroyObject(
TOmniRecordWrapper<T>.Create(value)))
else
{$IFDEF OTL_ERTTI}
In TOmniValue.CastTo<T>, following block
if ds = 0 then // complicated stuff
{$IFDEF OTL_ERTTI}
should be changed to
if ds = 0 then // complicated stuff
if ti.Kind = tkRecord then
Result := TOmniRecordWrapper<T>(CastToRecord.Value).Value
else
{$IFDEF OTL_ERTTI}

How to assign different labels to a set of classes using Matlab?

Can someone guide me to do this in the best possible way using matlab.
i have files with names 001_g_01.sig...001_g_08.sig, 002_g_01.sig...002_g_010.sig, 003_g_01.sig...003_g_08, upto n files.
what i want to do is assigning labels to files belong to one user (i.e.001_g_01.sig...001_g_08.sig as "User1", 002_g_01.sig...002_g_010.sig as "User2" and so on).
i have the following code to read the files.
dirName= '/FolderPath';
files = dir( fullfile(dirName,'001_g_1.Sig') );
files = {files.name};
dirName1= '/FolderPath';
files1 = dir( fullfile(dirName1,'*.Sig') );
files1 = {files1.name};
for i=1:length(files)
fname = fullfile(dirName,files{i});
%# some calculation
for j=i+1:length(files1)
fname1 = fullfile(dirName1,files1{j});
%# some calculation
end
end
files1 =
'001_g_01.sig'
'001_g_08.sig'
'003_g_01.sig'
.
.
If files1 is a cell like above, then you can write:
userlabel = {'001','002','003'};
f = cellstr(files1);
for ii = 1:3
result{ii} = strncmp(userlabel(ii),f,3);
end
You can do it in this way:
label = [repmat('User1',size(files,1),1); repmat('User2',size(files1,1),1) ];
This will create a array of labels containing 'User1' and 'User2'. If you need it separately, you can do it:
label1 = [repmat('User1',size(files,1),1)];

Array indexing in Confluence / Velocity templates

Our company has begun using Confluence wiki as a documentation site for our teams, and we are implementing a macro called PocketQuery.
This macro pulls SQL data into the site dynamically (we are pulling information like site contacts).
It uses Velocity Templates to display it's data, however I am having issues when doing simple array indexing.
The code:
#set ( $page = $additionalParams.get('Page') )
#set ( $pages = "" )
#if ( $page != $null && $page != "" )
#set ( $pages = $page.split(";") )
#else
#set ( $pages = [] )
#end
The $additionalParams is a list that has been initialised outside of the template, and contains the parameters being passed into macro, in this case:
Page=Site Name;Server
The code I am trying to setup is pulling the Name;Server value from the $additionalParams list, split the value if it is not empty, and then obtain the first value.
I have tried:
$pages.get(1)
$pages[1]
However no value gets pulled (I have also tried zero as an index - same result).
Foreach-ing through this array and printing each entry does work - meaning there are values in there.
All I want to be able to do is index into the array - Can't seem to dig up anyway of doing this.
Could this be converted to a list so it can use the $pages.get method to index into it?
Extending on that would this allow me to use $pages.contains method?
Confluence is using Velocity 1.6.
EDIT:
The solutions on this page and on this page do not work - I am guessing (Wildly) maybe the correct objects are not in the context for the template to use them?
(Would PocketQuery or Confluence be doing this?)
How would I go about using the 'ListTool' ?
The only way I could get this to work with any kind of elegance is as follows:
#set ( $Page = $additionalParams.get('Page') )
#set ( $Pages = [] )
#if ( $Page != $null && $Page != "" )
#foreach($i in $Page.split(";"))
$Pages.add($i)
#end
#end
This initialises a seperate array, loops through the split values and adds them to the seperate array, which seems to be able to use the methods provided in this question
I could then proceed to use it thus:
$Pages.get(0)//Would return "Site Name"
And also
$Pages.contains("Site Name")//Would return true
m.t.bennet is actually right - I tested and it works!!! I took about a month to find the asnwer and his code sniplet works
#set ( $Page = $additionalParams.get('Page') )
#set ( $Pages = [] )
#if ( $Page != $null && $Page != "" )
#foreach($i in $Page.split(";"))
$Pages.add($i)
#end
#end

Resources