XQuery: Subsequence of a sequence
Wednesday, 3 July 2019 · 4 messages
JC
Jordan Castillo3 Jul 2019 02:05 #
Hello BaseX Staff,
I am trying to access members of a sequence that I have created already, but it whenever I use the functions subsequence() it returns the entire sequence, and count() always returns 1.
The code:
xquery version "3.1";
declare namespace map="http://www.w3.org/2005/xpath-functions/map";
declare namespace xmi="http://www.omg.org/spec/XMI/20131001";
declare namespace uml="http://www.omg.org/spec/UML/20131001";
declare namespace MagicDraw_Profile="
http://www.omg.org/spec/UML/20131001/MagicDrawProfile";
declare namespace Extra_stereotypes="
http://www.magicdraw.com/schemas/Extra_stereotypes.xmi";
declare namespace UAF="http://www.omg.org/spec/UPDM/20121004/UPDM-Profile";
(
let $begin :=
db:open("CubeSatUML2.5XMIv3")/xmi:XMI/uml:Model/packagedElement
let $modelContent := $begin//packagedElement[@xmi:type="uml:Class"]
(: Combine the names of the elements with their ID's :)
let $names := $modelContent/@name
let $ids := $modelContent/@xmi:id
(: Grab all stereotypes, properties:[attributes, comments] :)
let $stereotypes := for $id in $ids
let $stereo1 := /xmi:XMI/*[@base_Element=$id]
let $stereo2 := /xmi:XMI/*[@base_Class=$id]
let $attributes := $begin//*[@xmi:id=$id]/ownedAttribute/[@name |
@xmi:type | @xmi:id]
let $comments := $begin//*[@xmi:id=$id]/ownedComment/[@name | @xmi:type
| @xmi:id | @body]
let $combined := ($id, $stereo1/name(), $stereo2/name(), $comments,
$attributes, "")
return $combined
let $final :=
for $seq in $stereotypes
return subsequence($seq, 1, 1)
(: ^ the part in question:)
return $final
)I realize I am creating this in a very weird way, but I want to keep the data together and have not thought of another solution.
I have tried 'for each'ing over the '$sequences' and tokenizing to get the elements out, but I get an error:
let $finalMap :=
for $seq in $stereotypes
return tokenize($seq, '\s')
[XPTY0004] Item expected, sequence found: ("uml:Property",
"_18_5_2_4c1014b_153850....
When I print '$stereotypes', I get what appears to be a sequence of sequences (which I don't think is a real thing, but it appears to be that)
Ex output:
xmi:id="_18_5_2_4c1014b_1538500371989_609286_80522"
UAF:ResourceArtifact
[(xmi:type="uml:Property",
xmi:id="_18_5_2_4c1014b_1538500468390_289646_80939", name="flight")] [(xmi:type="uml:Property",
xmi:id="_18_5_2_4c1014b_1538500488269_847951_81240", name="ground")]
xmi:id="_18_5_2_4c1014b_1538500376501_394659_80590"
UAF:ResourceArtifact
[(xmi:type="uml:Comment",
xmi:id="_18_5_2_4c1014b_1538501028725_896600_82978", body="The ground supporting equipment and operations that support the spacecraft mission.")] [(xmi:type="uml:Property",
xmi:id="_18_5_2_4c1014b_1538500492755_533021_81326", name="ground Communications")]
[(xmi:type="uml:Property",
xmi:id="_18_5_2_4c1014b_1538500495333_439654_81369", name="ground Command and Control")]
[(xmi:type="uml:Port", xmi:id="_18_5_2_4c1014b_1538582001724_435913_83660", name="Flight_Ground")]
My end goal is to have a map of maps, where the root map has keys of element names (currently in $names) and the value is a map of all the properties of this element.
To do this I have to deconstruct this monster I have created, and maybe I am on the wrong path entirely but some direction would be greatly appreciated.
End goal format:
map{
elementName : map {
stereotypes: map{
stereotype_Name_1: stereotype_ID_1,
stereotype_Name_2: stereotype_ID_2
},
attributeName: map{
'id': actual_ID_here,
'lowerValue': someValue,
'upperValue': "*"
},
comment: map{
'id': actual_ID_here,
'xmi:type': 'uml:Comment',
'body': actual_Comment_Here
},
'id': actual_ID_here
}
}
Thanks,
Jordan Castillo
</longWindedQuestion>
JC
Jordan Castillo3 Jul 2019 02:27 #
BaseX team,
Sorry for the long question but I just figured out what is going on...
The '$stereotypes' is a gigantic sequence, which is why I can't separate its members into sequences.
Hope you guys have a great week,
Jordan Castillo
Quoted text · Jordan Castillo · 120 lines
On Tue, Jul 2, 2019 at 3:05 PM Jordan Castillo < jordantcastillo1992 at gmail.com> wrote: > Hello BaseX Staff, > > I am trying to access members of a sequence that I have created already, > but it whenever I use the functions subsequence() it returns the entire > sequence, and count() always returns 1. > > > > The code: > xquery version "3.1"; > declare namespace map="http://www.w3.org/2005/xpath-functions/map"; > declare namespace xmi="http://www.omg.org/spec/XMI/20131001"; > declare namespace uml="http://www.omg.org/spec/UML/20131001"; > declare namespace MagicDraw_Profile=" > http://www.omg.org/spec/UML/20131001/MagicDrawProfile"; > declare namespace Extra_stereotypes=" > http://www.magicdraw.com/schemas/Extra_stereotypes.xmi"; > declare namespace UAF="http://www.omg.org/spec/UPDM/20121004/UPDM-Profile > "; > ( > let $begin := > db:open("CubeSatUML2.5XMIv3")/xmi:XMI/uml:Model/packagedElement > let $modelContent := $begin//packagedElement[@xmi:type="uml:Class"] > (: Combine the names of the elements with their ID's :) > let $names := $modelContent/@name > let $ids := $modelContent/@xmi:id > (: Grab all stereotypes, properties:[attributes, comments] :) > let $stereotypes := for $id in $ids > let $stereo1 := /xmi:XMI/*[@base_Element=$id] > let $stereo2 := /xmi:XMI/*[@base_Class=$id] > let $attributes := $begin//*[@xmi:id=$id]/ownedAttribute/[@name | > @xmi:type | @xmi:id] > let $comments := $begin//*[@xmi:id=$id]/ownedComment/[@name | > @xmi:type | @xmi:id | @body] > let $combined := ($id, $stereo1/name(), $stereo2/name(), $comments, > $attributes, "") > return $combined > > let $final := > for $seq in $stereotypes > return subsequence($seq, 1, 1) > (: ^ the part in question:) > > return $final > ) > > I realize I am creating this in a very weird way, but I want to keep the > data together and have not thought of another solution. > I have tried 'for each'ing over the '$sequences' and tokenizing to get the > elements out, but I get an error: > let $finalMap := > for $seq in $stereotypes > return tokenize($seq, '\s') > [XPTY0004] Item expected, sequence found: ("uml:Property", > "_18_5_2_4c1014b_153850.... > > > When I print '$stereotypes', I get what appears to be a sequence of > sequences (which I don't think is a real thing, but it appears to be that) > > Ex output: > > xmi:id="_18_5_2_4c1014b_1538500371989_609286_80522" > UAF:ResourceArtifact > [(xmi:type="uml:Property", > xmi:id="_18_5_2_4c1014b_1538500468390_289646_80939", name="flight")] > [(xmi:type="uml:Property", > xmi:id="_18_5_2_4c1014b_1538500488269_847951_81240", name="ground")] > > xmi:id="_18_5_2_4c1014b_1538500376501_394659_80590" > UAF:ResourceArtifact > [(xmi:type="uml:Comment", > xmi:id="_18_5_2_4c1014b_1538501028725_896600_82978", body="The ground > supporting equipment and operations that support the spacecraft mission.")] > [(xmi:type="uml:Property", > xmi:id="_18_5_2_4c1014b_1538500492755_533021_81326", name="ground > Communications")] > [(xmi:type="uml:Property", > xmi:id="_18_5_2_4c1014b_1538500495333_439654_81369", name="ground Command > and Control")] > [(xmi:type="uml:Port", > xmi:id="_18_5_2_4c1014b_1538582001724_435913_83660", name="Flight_Ground")] > > My end goal is to have a map of maps, where the root map has keys of > element names (currently in $names) and the value is a map of all the > properties of this element. > To do this I have to deconstruct this monster I have created, and maybe I > am on the wrong path entirely but some direction would be greatly > appreciated. > > End goal format: > > map{ > elementName : map { > stereotypes: map{ > stereotype_Name_1: stereotype_ID_1, > stereotype_Name_2: stereotype_ID_2 > }, > attributeName: map{ > 'id': actual_ID_here, > 'lowerValue': someValue, > 'upperValue': "*" > }, > comment: map{ > 'id': actual_ID_here, > 'xmi:type': 'uml:Comment', > 'body': actual_Comment_Here > }, > 'id': actual_ID_here > } > } > > Thanks, > > Jordan Castillo > </longWindedQuestion> > >
BD
Bridger Dyson-Smith3 Jul 2019 03:00 #
Hi Jordan,
Maybe the
fn:head(), fn:tail(), and other functions for sequence operations would help[1]?
HTH!
Best,
Bridger
[1] https://www.w3.org/TR/xpath-functions-31/#sequence-functionsQuoted text · Jordan Castillo · 134 lines
On Tue, Jul 2, 2019, 6:27 PM Jordan Castillo <jordantcastillo1992 at gmail.com> wrote: > BaseX team, > > Sorry for the long question but I just figured out what is going on... > > The '$stereotypes' is a gigantic sequence, which is why I can't separate > its members into sequences. > > Hope you guys have a great week, > > Jordan Castillo > > On Tue, Jul 2, 2019 at 3:05 PM Jordan Castillo < > jordantcastillo1992 at gmail.com> wrote: > >> Hello BaseX Staff, >> >> I am trying to access members of a sequence that I have created already, >> but it whenever I use the functions subsequence() it returns the entire >> sequence, and count() always returns 1. >> >> >> >> The code: >> xquery version "3.1"; >> declare namespace map="http://www.w3.org/2005/xpath-functions/map"; >> declare namespace xmi="http://www.omg.org/spec/XMI/20131001"; >> declare namespace uml="http://www.omg.org/spec/UML/20131001"; >> declare namespace MagicDraw_Profile=" >> http://www.omg.org/spec/UML/20131001/MagicDrawProfile"; >> declare namespace Extra_stereotypes=" >> http://www.magicdraw.com/schemas/Extra_stereotypes.xmi"; >> declare namespace UAF="http://www.omg.org/spec/UPDM/20121004/UPDM-Profile >> "; >> ( >> let $begin := >> db:open("CubeSatUML2.5XMIv3")/xmi:XMI/uml:Model/packagedElement >> let $modelContent := $begin//packagedElement[@xmi:type="uml:Class"] >> (: Combine the names of the elements with their ID's :) >> let $names := $modelContent/@name >> let $ids := $modelContent/@xmi:id >> (: Grab all stereotypes, properties:[attributes, comments] :) >> let $stereotypes := for $id in $ids >> let $stereo1 := /xmi:XMI/*[@base_Element=$id] >> let $stereo2 := /xmi:XMI/*[@base_Class=$id] >> let $attributes := $begin//*[@xmi:id=$id]/ownedAttribute/[@name | >> @xmi:type | @xmi:id] >> let $comments := $begin//*[@xmi:id=$id]/ownedComment/[@name | >> @xmi:type | @xmi:id | @body] >> let $combined := ($id, $stereo1/name(), $stereo2/name(), $comments, >> $attributes, "") >> return $combined >> >> let $final := >> for $seq in $stereotypes >> return subsequence($seq, 1, 1) >> (: ^ the part in question:) >> >> return $final >> ) >> >> I realize I am creating this in a very weird way, but I want to keep the >> data together and have not thought of another solution. >> I have tried 'for each'ing over the '$sequences' and tokenizing to get >> the elements out, but I get an error: >> let $finalMap := >> for $seq in $stereotypes >> return tokenize($seq, '\s') >> [XPTY0004] Item expected, sequence found: ("uml:Property", >> "_18_5_2_4c1014b_153850.... >> >> >> When I print '$stereotypes', I get what appears to be a sequence of >> sequences (which I don't think is a real thing, but it appears to be that) >> >> Ex output: >> >> xmi:id="_18_5_2_4c1014b_1538500371989_609286_80522" >> UAF:ResourceArtifact >> [(xmi:type="uml:Property", >> xmi:id="_18_5_2_4c1014b_1538500468390_289646_80939", name="flight")] >> [(xmi:type="uml:Property", >> xmi:id="_18_5_2_4c1014b_1538500488269_847951_81240", name="ground")] >> >> xmi:id="_18_5_2_4c1014b_1538500376501_394659_80590" >> UAF:ResourceArtifact >> [(xmi:type="uml:Comment", >> xmi:id="_18_5_2_4c1014b_1538501028725_896600_82978", body="The ground >> supporting equipment and operations that support the spacecraft mission.")] >> [(xmi:type="uml:Property", >> xmi:id="_18_5_2_4c1014b_1538500492755_533021_81326", name="ground >> Communications")] >> [(xmi:type="uml:Property", >> xmi:id="_18_5_2_4c1014b_1538500495333_439654_81369", name="ground Command >> and Control")] >> [(xmi:type="uml:Port", >> xmi:id="_18_5_2_4c1014b_1538582001724_435913_83660", name="Flight_Ground")] >> >> My end goal is to have a map of maps, where the root map has keys of >> element names (currently in $names) and the value is a map of all the >> properties of this element. >> To do this I have to deconstruct this monster I have created, and maybe I >> am on the wrong path entirely but some direction would be greatly >> appreciated. >> >> End goal format: >> >> map{ >> elementName : map { >> stereotypes: map{ >> stereotype_Name_1: stereotype_ID_1, >> stereotype_Name_2: stereotype_ID_2 >> }, >> attributeName: map{ >> 'id': actual_ID_here, >> 'lowerValue': someValue, >> 'upperValue': "*" >> }, >> comment: map{ >> 'id': actual_ID_here, >> 'xmi:type': 'uml:Comment', >> 'body': actual_Comment_Here >> }, >> 'id': actual_ID_here >> } >> } >> >> Thanks, >> >> Jordan Castillo >> </longWindedQuestion> >> >>
CG
Hi Jordan,
I’m glad to hear you solved the problem. Just a minor observation:
Quoted text · Jordan Castillo · 1 line
> let $attributes := $begin//*[@xmi:id=$id]/ownedAttribute/[@name | @xmi:type | @xmi:id]
This query will create an XQuery array for each ownedAttribute element (with 3 attributes inside). You could additionally create an array for each stereotype item:
Quoted text · Jordan Castillo · 1 line
> let $combined := [ $id, $stereo1/name(), $stereo2/name(), $comments, $attributes, "" ]
Later on, if you use subsequence(), head() or ...[1], you will get one single stereotype array item…
let $first := subsequence($stereotypes, 1)
let $first := head($subsequence) (: equivalent :)
let $first := $subsequence[1] (: equivalent :)…and you can further process the array entries in the next step:
let $first-id := $first(1) (: access first array entry :)
return $first-idMaybe this helps you to build up the final map representation? The lookup operator (?) can be used for positional access. If $stereotype contains the array sequence (as generated above in my reply), it is very simple to retrieve the first member of all all arrays:
let $ids := $sterotypes?1See [1,2] for more information on arrays and the lookup operator.
Cheers,
Christian
[1] http://docs.basex.org/wiki/XQuery_3.1
[2] http://docs.basex.org/wiki/Array_Module
Written for BaseX 9.2. BaseX may have changed since: please check the current documentation.
⚡Generated with XQuery