How can I increment the x variable only when numerical is false? (I've been reading how xquery isn't iterative...)
current output:
<xml> <person id="1" x="0" numerical="false">people</person> <person id="2" x="0" numerical="false">joe</person> <person id="3" x="0" numerical="true">phone1</person> <person id="4" x="0" numerical="true">phone2</person> <person id="5" x="0" numerical="true">phone3</person> <person id="6" x="0" numerical="false">sue</person> <person id="7" x="0" numerical="true">cell4</person> <person id="8" x="0" numerical="true">home5</person> <person id="9" x="0" numerical="false">alice</person> <person id="10" x="0" numerical="true">atrib6</person> <person id="11" x="0" numerical="true">x7</person> <person id="12" x="0" numerical="true">y9</person> <person id="13" x="0" numerical="true">z10</person> </xml>
desired output:
<xml> <person id="1" x="1" numerical="false">people</person> <person id="2" x="2" numerical="false">joe</person> <person id="3" x="2" numerical="true">phone1</person> <person id="4" x="2" numerical="true">phone2</person> ... </xml>
Maybe with a second xquery? Here's the first:
xquery version "3.0";
<xml>
{ variable $x:=0;
for $line in db:open("foo.txt")//text()
count $id
return if (matches($line, "[0-9]")) then <person id='{$id}' x='{$x}' numerical="true">{$line}</person> else <person id='{$id}' x='{$x}' numerical="false">{$line}</person> } </xml>
where I'm trying to use attributes because I'm not sure how to conditionally nest tags. But, this is interesting. Not quite sure on syntax to set and then conditionally increment $x, however.
thanks,
Thufir
How do I decrement y?
Pardon, output for a simpler example:
<xy x="1" y="98"/> <xy x="2" y="98"/> <xy x="3" y="98"/> <xy x="4" y="98"/> <xy x="5" y="98"/> <xy x="6" y="98"/> <xy x="7" y="98"/> <xy x="8" y="98"/> <xy x="9" y="98"/>
the FLWOR:
xquery version "3.0"; let $y := 99 for $x in (1 to 9) let $y := $y - 1 return <xy x='{$x}' y='{$y}' />
is it not possible to decrement $y without using some external scripting function? That seems odd.
thanks,
Thufir
Hi Thufir -
Maybe something like this will help?
``` xquery version "3.1";
let $y := 99
for $x in (1 to 9) count $iterator let $decrease := $y - $iterator return( comment { "iterator = " || $iterator }, comment { "decrease = " || $decrease }, <xy x='{ $x }' y='{ $decrease }'/> ) ```
I'm basically ripping Walmsley's book off for this example -- see pages ~135-7 (examples P-6,7). The `count` clause makes this work.
Best, Bridger
PS Remember, the first step in avoiding a *trap* is knowing of its existence. :)
On Wed, Feb 19, 2020 at 10:33 AM thufir hawat.thufir@gmail.com wrote:
How do I decrement y?
Pardon, output for a simpler example:
<xy x="1" y="98"/> <xy x="2" y="98"/> <xy x="3" y="98"/> <xy x="4" y="98"/> <xy x="5" y="98"/> <xy x="6" y="98"/> <xy x="7" y="98"/> <xy x="8" y="98"/> <xy x="9" y="98"/>
the FLWOR:
xquery version "3.0"; let $y := 99 for $x in (1 to 9) let $y := $y - 1 return <xy x='{$x}' y='{$y}' />
is it not possible to decrement $y without using some external scripting function? That seems odd.
thanks,
Thufir
Hi Bridger,
Yes, this may very well. I'll dive into it later today or tomorrow. The difficulty for me will be to decrement only if a conditional. But, that may very well suffice.
If so, it will give the data some structure through attributes.
Then, I can use those attributes.
Thanks,
Thufi
On 2020-02-19 7:57 a.m., Bridger Dyson-Smith wrote:
Hi Thufir -
Maybe something like this will help?
xquery version "3.1"; let $y := 99 for $x in (1 to 9) count $iterator let $decrease := $y - $iterator return( comment { "iterator = " || $iterator }, comment { "decrease = " || $decrease }, <xy x='{ $x }' y='{ $decrease }'/> )
I'm basically ripping Walmsley's book off for this example -- see pages ~135-7 (examples P-6,7). The `count` clause makes this work.
Best, Bridger
PS Remember, the first step in avoiding a *trap* is knowing of its existence. :)
On Wed, Feb 19, 2020 at 10:33 AM thufir <hawat.thufir@gmail.com mailto:hawat.thufir@gmail.com> wrote:
How do I decrement y? Pardon, output for a simpler example: <xy x="1" y="98"/> <xy x="2" y="98"/> <xy x="3" y="98"/> <xy x="4" y="98"/> <xy x="5" y="98"/> <xy x="6" y="98"/> <xy x="7" y="98"/> <xy x="8" y="98"/> <xy x="9" y="98"/> the FLWOR: xquery version "3.0"; let $y := 99 for $x in (1 to 9) let $y := $y - 1 return <xy x='{$x}' y='{$y}' /> is it not possible to decrement $y without using some external scripting function? That seems odd. thanks, Thufir
On Feb 19, 2020, at 10:01 AM, thufir hawat.thufir@gmail.com wrote:
where I'm trying to use attributes because I'm not sure how to conditionally nest tags. But, this is interesting. Not quite sure on syntax to set and then conditionally increment $x, however.
Does “conditionally nest tags” mean that you want to make the person[@numerical=“true”] elements children of the immediately previous person[@numerical=“false”] elements ?
If that is the case you can use “group by”
— Steve M.
Hi Steve,
yes, it certainly does. At this point, I'd settle for adding an attribute like "recordID", but that's exactly it. I'll take a closer look at "group by" a bit later, thanks for the pointer. See also:
https://stackoverflow.com/q/60237739/262852
thanks,
Thufir
On 2020-02-19 1:05 p.m., Majewski, Steven Dennis (sdm7g) wrote:
On Feb 19, 2020, at 10:01 AM, thufir <hawat.thufir@gmail.com mailto:hawat.thufir@gmail.com> wrote:
where I'm trying to use attributes because I'm not sure how to conditionally nest tags. But, this is interesting. Not quite sure on syntax to set and then conditionally increment $x, however.
Does “conditionally nest tags” mean that you want to make the person[@numerical=“true”] elements children of the immediately previous person[@numerical=“false”] elements ?
If that is the case you can use “group by”
— Steve M.
The reason I asked was: although XQuery looks more procedural than XSLT, it’s still basically a functional and declarative language, and thinking about incrementing or decrementing variables is probably the wrong way to think about solving your problem in XQuery. Variables bind names to values over a particular scope, and they aren’t updatable variables that you can increment or decrement.
If what you want in English is roughly: For person element where numerical = true , group by the preceding-sibling where numerical = false
That maps fairly simply into XQuery syntax:
declare variable $XML := <xml> <person id="1" x="0" numerical="false">people</person> <person id="2" x="0" numerical="false">joe</person> <person id="3" x="0" numerical="true">phone1</person> <person id="4" x="0" numerical="true">phone2</person> <person id="5" x="0" numerical="true">phone3</person> <person id="6" x="0" numerical="false">sue</person> <person id="7" x="0" numerical="true">cell4</person> <person id="8" x="0" numerical="true">home5</person> <person id="9" x="0" numerical="false">alice</person> <person id="10" x="0" numerical="true">atrib6</person> <person id="11" x="0" numerical="true">x7</person> <person id="12" x="0" numerical="true">y9</person> <person id="13" x="0" numerical="true">z10</person> </xml> ;
for $P in $XML/person where $P[@numerical="true"] let $PREV := $P/preceding-sibling::person[@numerical="false"][1] group by $PREV return <person name="{$PREV}" > { $P } </person>
Yields:
<person name="joe"> <person id="3" x="0" numerical="true">phone1</person> <person id="4" x="0" numerical="true">phone2</person> <person id="5" x="0" numerical="true">phone3</person> </person> <person name="sue"> <person id="7" x="0" numerical="true">cell4</person> <person id="8" x="0" numerical="true">home5</person> </person> <person name="alice"> <person id="10" x="0" numerical="true">atrib6</person> <person id="11" x="0" numerical="true">x7</person> <person id="12" x="0" numerical="true">y9</person> <person id="13" x="0" numerical="true">z10</person> </person>
Once the grouping is working, you can work on tweaking the output format to exactly what you want. I tried to work towards something like what I THOUGHT you might want. I had a bit of trouble understanding that $PREV in the return expression is an atomic string value and not a node, and that the other variables in return expression are multiple valued ( thus the ‘[1]’s ), but I ended up with this:
<people> { for $P in $XML/person where $P[@numerical="true"] let $PREV := $P/preceding-sibling::person[@numerical="false"][1] let $X := count($P[1]/preceding-sibling::person[@numerical="false"]) group by $PREV return <person name="{$PREV}" x="{$X[1] - 1 }" id="{$P[1]/preceding-sibling::person[@numerical="false"][1]/@id}"
{ for $I in $P return <number>{$I/@id, attribute x {$X[1]-1}, string($I)}</number> } </person>
} </people>
Which yields:
<people> <person name="joe" x="1" id="2"> <number id="3" x="1">phone1</number> <number id="4" x="1">phone2</number> <number id="5" x="1">phone3</number> </person> <person name="sue" x="2" id="6"> <number id="7" x="2">cell4</number> <number id="8" x="2">home5</number> </person> <person name="alice" x="3" id="9"> <number id="10" x="3">atrib6</number> <number id="11" x="3">x7</number> <number id="12" x="3">y9</number> <number id="13" x="3">z10</number> </person> </people>
Also more functional to think of use count or position expressions instead of incrementing or decrementing variables.
I’m hitting the Walmsley book myself now to try to understand those issues with group by / return that were puzzling to me.
— Steve M.
On Feb 19, 2020, at 8:28 PM, thufir hawat.thufir@gmail.com wrote:
Hi Steve,
yes, it certainly does. At this point, I'd settle for adding an attribute like "recordID", but that's exactly it. I'll take a closer look at "group by" a bit later, thanks for the pointer. See also:
https://stackoverflow.com/q/60237739/262852
thanks,
Thufir
On 2020-02-19 1:05 p.m., Majewski, Steven Dennis (sdm7g) wrote:
On Feb 19, 2020, at 10:01 AM, thufir <hawat.thufir@gmail.com mailto:hawat.thufir@gmail.com> wrote:
where I'm trying to use attributes because I'm not sure how to conditionally nest tags. But, this is interesting. Not quite sure on syntax to set and then conditionally increment $x, however.
Does “conditionally nest tags” mean that you want to make the person[@numerical=“true”] elements children of the immediately previous person[@numerical=“false”] elements ? If that is the case you can use “group by” — Steve M.
Yes, that's pretty much it:
https://stackoverflow.com/q/60237739/262852
I'm a bit curious what happened to the "people" group, but I'll test and adapt. Did "people" get dropped because it has no following siblings to group with?
thanks,
Thufir
On 2020-02-19 6:55 p.m., Majewski, Steven Dennis (sdm7g) wrote:
The reason I asked was: although XQuery looks more procedural than XSLT, it’s still basically a functional and declarative language, and thinking about incrementing or decrementing variables is probably the wrong way to think about solving your problem in XQuery. Variables bind names to values over a particular scope, and they aren’t updatable variables that you can increment or decrement.
If what you want in English is roughly: For person element where numerical = true , group by the preceding-sibling where numerical = false
That maps fairly simply into XQuery syntax:
declare variable $XML := <xml> <person id="1" x="0" numerical="false">people</person> <person id="2" x="0" numerical="false">joe</person> <person id="3" x="0" numerical="true">phone1</person> <person id="4" x="0" numerical="true">phone2</person> <person id="5" x="0" numerical="true">phone3</person> <person id="6" x="0" numerical="false">sue</person> <person id="7" x="0" numerical="true">cell4</person> <person id="8" x="0" numerical="true">home5</person> <person id="9" x="0" numerical="false">alice</person> <person id="10" x="0" numerical="true">atrib6</person> <person id="11" x="0" numerical="true">x7</person> <person id="12" x="0" numerical="true">y9</person> <person id="13" x="0" numerical="true">z10</person> </xml> ;
for $P in $XML/person where $P[@numerical="true"] let $PREV := $P/preceding-sibling::person[@numerical="false"][1] group by $PREV return <person name="{$PREV}" > { $P } </person>
Yields:
<person name="joe"> <person id="3" x="0" numerical="true">phone1</person> <person id="4" x="0" numerical="true">phone2</person> <person id="5" x="0" numerical="true">phone3</person> </person> <person name="sue"> <person id="7" x="0" numerical="true">cell4</person> <person id="8" x="0" numerical="true">home5</person> </person> <person name="alice"> <person id="10" x="0" numerical="true">atrib6</person> <person id="11" x="0" numerical="true">x7</person> <person id="12" x="0" numerical="true">y9</person> <person id="13" x="0" numerical="true">z10</person> </person>
Once the grouping is working, you can work on tweaking the output format to exactly what you want. I tried to work towards something like what I THOUGHT you might want. I had a bit of trouble understanding that $PREV in the return expression is an atomic string value and not a node, and that the other variables in return expression are multiple valued ( thus the ‘[1]’s ), but I ended up with this:
<people> { for $P in $XML/person where $P[@numerical="true"] let $PREV := $P/preceding-sibling::person[@numerical="false"][1] let $X := count($P[1]/preceding-sibling::person[@numerical="false"]) group by $PREV return <person name="{$PREV}" x="{$X[1] - 1 }" id="{$P[1]/preceding-sibling::person[@numerical="false"][1]/@id}"
{ for $I in $P return <number>{$I/@id, attribute x {$X[1]-1}, string($I)}</number> } </person>
} </people>
Which yields:
<people> <person name="joe" x="1" id="2"> <number id="3" x="1">phone1</number> <number id="4" x="1">phone2</number> <number id="5" x="1">phone3</number> </person> <person name="sue" x="2" id="6"> <number id="7" x="2">cell4</number> <number id="8" x="2">home5</number> </person> <person name="alice" x="3" id="9"> <number id="10" x="3">atrib6</number> <number id="11" x="3">x7</number> <number id="12" x="3">y9</number> <number id="13" x="3">z10</number> </person> </people>
Also more functional to think of use count or position expressions instead of incrementing or decrementing variables.
I’m hitting the Walmsley book myself now to try to understand those issues with group by / return that were puzzling to me.
— Steve M.
On Feb 19, 2020, at 8:28 PM, thufir <hawat.thufir@gmail.com mailto:hawat.thufir@gmail.com> wrote:
Hi Steve,
yes, it certainly does. At this point, I'd settle for adding an attribute like "recordID", but that's exactly it. I'll take a closer look at "group by" a bit later, thanks for the pointer. See also:
https://stackoverflow.com/q/60237739/262852
thanks,
Thufir
On 2020-02-19 1:05 p.m., Majewski, Steven Dennis (sdm7g) wrote:
On Feb 19, 2020, at 10:01 AM, thufir <hawat.thufir@gmail.com mailto:hawat.thufir@gmail.com> wrote:
where I'm trying to use attributes because I'm not sure how to conditionally nest tags. But, this is interesting. Not quite sure on syntax to set and then conditionally increment $x, however.
Does “conditionally nest tags” mean that you want to make the person[@numerical=“true”] elements children of the immediately previous person[@numerical=“false”] elements ? If that is the case you can use “group by” — Steve M.
basex-talk@mailman.uni-konstanz.de