how to group result in xquery - xquery

Sorry for the title, I didnt know what's the best title for this question
I'm having difficulties with XQUERY. The result is not what I expected
here's the xml
<Equipes>
<Equipe>
<equipeId>1</equipeId>
<equipeNom>Equipe A</equipeNom>
<JoueurEquipe>
<dateDebut>2011-01-01</dateDebut>
<dateFin>2013-01-01</dateFin>
<numero>1</numero>
<joueurId>1</joueurId>
</JoueurEquipe>
<JoueurEquipe>
<dateDebut>2010-01-01</dateDebut>
<dateFin>2012-01-01</dateFin>
<numero>2</numero>
<joueurId>2</joueurId>
</JoueurEquipe>
</Equipe>
<Equipe>
<equipeId>2</equipeId>
<equipeNom>Equipe B</equipeNom>
<JoueurEquipe>
<dateDebut>2009-01-01</dateDebut>
<dateFin>2012-01-01</dateFin>
<numero>1</numero>
<joueurId>3</joueurId>
</JoueurEquipe>
<JoueurEquipe>
<dateDebut>2010-01-01</dateDebut>
<dateFin>2014-01-01</dateFin>
<numero>2</numero>
<joueurId>4</joueurId>
</JoueurEquipe>
</Equipe>
</Equipes>
and here's the query
for $b in doc("ligue.xml")/ligue/Equipes
return
<Equipes>
{
$b/Equipe/equipeId,
$b/Equipe/equipeNom
}
</Equipes>
the result is
<equipes>
<equipeId>1</equipeId>
<equipeId>2</equipeId>
<equipeNom>Equipe A</equipeNom>
<equipeNom>Equipe B</equipeNom>
</equipes>
what I need is
<equipes>
<equipeId>1</equipeId>
<equipeNom>Equipe A</equipeNom>
<equipeId>2</equipeId>
<equipeNom>Equipe B</equipeNom>
</equipes>
I don't know what i'm missing
Thank you

Iterate over the things you actually want your output to iterate over:
<Equipes>{
for $b in doc("ligue.xml")/ligue/Equipes/Equipe[equipeId][equipeNom]
return ($b/equipeId, $b/equipeNom)
}</Equipes>
Now, let's explore why your prior query behaved as it did. This:
for $b in doc("ligue.xml")/ligue/Equipes
return
<Equipes>
{
$b/Equipe/equipeId,
$b/Equipe/equipeNom
}
</Equipes>
...finds the Equipes element, of which there's only one (making the for loop useless). It then searches for $b/Equipe/equipeId and $b/Equipe/equipeNom, both of which evaluate to lists containing multiple elements, and concatenates those two lists to get the output.

Related

XQuery how to count with "where" condition

I'm just starting to learn XQuery and I want that it shows me the number of festivals with genre (genero) is the same as "metal". I can't get the total number of them, only separately.
Xquery
for $b in //festival
where $b/#genero="Metal"
return <prueba>{count ($b/#genero="Metal"), $b//nombre}</prueba>
XML
<Festivales>
<festival genero="Metal">
<informacion>
<nombre>Resurrection Fest</nombre>
<fecha_inicio>2020-07-01</fecha_inicio>
<fecha_fin>2020-07-04</fecha_fin>
</festival>
<festival genero="Rock-Heavy Metal">
<informacion>
<nombre>Rock the Night</nombre>
<fecha_inicio>2020-06-26</fecha_inicio>
<fecha_fin>2020-06-27</fecha_fin>
</festival>
<festival genero="Hardcore">
<informacion>
<nombre>Ieperfest</nombre>
<fecha_inicio>2020-07-03</fecha_inicio>
<fecha_fin>2020-07-05</fecha_fin>
</informacion>
</festival>
<festival genero="Metal">
<informacion>
<nombre>Download UK</nombre>
<fecha_inicio>2020-06-12</fecha_inicio>
<fecha_fin>2020-06-14</fecha_fin>
</informacion>
</festival>
</Festivales>
Result
<prueba>1<nombre>Resurrection Fest</nombre>
</prueba>
<prueba>1<nombre>Hellfest</nombre>
</prueba>
<prueba>1<nombre>Download UK</nombre>
</prueba>
Thanks!
for $b in //festival[#genero="Metal"]
let $n := $b/informacion/nombre/text()
return
<prueba>
{
<cnt>{count(//festival[#genero="Metal"]/informacion/nombre[. = $n])}</cnt>
, $b/informacion/nombre
}
</prueba>

How can I use R Regular Expressions to catch a Hebrew word?

I've been trying to catch the word
עונה
plus the subsequent number after it in a string such as
כל הילדים אוכלים, עונה 2 , פרק 8-לזניית ירקות וסלמון בדבש
Demonstrating it on Regex101.com was straightforward enough, with עונה(\s+\d+|\d+), but with R I came up empty.
str<-"כל הילדים אוכלים, עונה 2 , פרק 8-לזניית ירקות וסלמון בדבש"
exp<-"עונה(\\s+\\d+|\\d+)"
str_extract_all(str,exp)
Output:
[[1]]
character(0)
You can use this regex:
/[\u0590-\u05FF]/*

Add Header to an XML to CSV conversion using XQuery

Hi I am trying to convert some xml to csv using xquery and found a previous post that helped me get to this point:
for $b in /root/Result
return
concat(escape-html-uri(string-join(($b/HolidayEndDate,
$b/HolidayType,
$b/FirstName,
$b/AllowanceRemainingDays,
$b/HolidayStartDate,
$b/EmployeeId,
$b/AllowanceDays,
$b/LastName,
$b/HolidayDurationDays
)
/normalize-space(),
",")
),
codepoints-to-string(10))
This returns all of the data as required but no Header row. Is there a simple addition to the above code that would also return the header row? Thanks. :)
Since your query returns a sequence of lines, you can just prepend another line before the FLWOR expression:
"HolidayEndDate,HolidayType,FirstName,AllowanceRemainingDays,HolidayStartDate,EmployeeId,AllowanceDays,LastName,HolidayDurationDays
",
for $b in /root/Result
return
concat(escape-html-uri(string-join(($b/HolidayEndDate,
$b/HolidayType,
$b/FirstName,
$b/AllowanceRemainingDays,
$b/HolidayStartDate,
$b/EmployeeId,
$b/AllowanceDays,
$b/LastName,
$b/HolidayDurationDays
)
/normalize-space(),
",")
),
codepoints-to-string(10))
Because nested sequences are flattened (i.e. concatenated) in XQuery, this results in one output sequence including the header. Note also that I used a character entity '
' for the newline character, which is much shorter than codepoints-to-string(10).
concat("HolidayEndDate,HolidayType,FirstName,AllowanceRemainingDays,HolidayStartDate,EmployeeId,AllowanceDays,LastName,HolidayDurationDays
",
string-join(
for $b in /root/Result
return
concat(escape-html-uri(string-join(($b/HolidayEndDate,
$b/HolidayType,
$b/FirstName,
$b/AllowanceRemainingDays,
$b/HolidayStartDate,
$b/EmployeeId,
$b/AllowanceDays,
$b/LastName,
$b/HolidayDurationDays
)
/normalize-space(),
",")
),
codepoints-to-string(10)), "")
)

How to perform a 'join' with a sub element in XQuery

Im not sure how to word what I am trying to do, but I am trying to get all touples of FID, BID, and Something. Consider the following XML:
<FOO>
<FID>f1</FID>
<NAME>f1</NAME>
<BAR>
<BID>b1</BID>
<SOMETHING>15</SOMETHING>
</BAR>
<BAR>
<BID>b2</BID>
<SOMETHING>25</SOMETHING>
</BAR>
</FOO>
<FOO>
<FID>f2</FID>
<NAME>f2</NAME>
<BAR>
<BID>b1</BID>
<SOMETHING>35</SOMETHING>
</BAR>
<BAR>
<BID>b3</BID>
<SOMETHING>0</SOMETHING>
</BAR>
</FOO>
What I need is:
b1 f1 15
b1 f2 35
b2 f1 25
b3 f2 0
Anyone know the syntax that I would use?
I tried:
for $foo in /root/FOO
for $bar in /root/FOO/BAR
let $fid := $foo/FID/text() where $foo/BAR/BID/text()=$bar/BID/text()
let $bid := $foo/BAR/BID/text() where $foo/BAR/BID/text()=$bar/BID/text()
let $something := $foo/BAR/SOMETHING/text() where $foo/BAR/BID/text()=$bar/BID/text()
If you'd wanted to order by the <FID/> elements first, it'd be as easy as looping over the <FOO/>s, for each of them over its <BAR/>s and dumping a string each time:
for $foo in /root/FOO
for $bar in /BAR
return string-join(($foo/FID, $bar/BID, $bar/SOMETHING), ' ')
For grouping by <BID/>s, you have to loop over those first and collect the other information relatively:
for $bar in //BAR
order by $bar/BID
return string-join(($bar/BID, $bar/../FID, $bar/SOMETHING), ' ')
A small remark (as I wasn't able to run your code without major cleanup): $foo and $FOO are not the same, XQuery is case sensitive. Furthermore, you're missing a return clause.

xQuery category nesting issue

I have a problem nesting the result tags in each other the right way.
The result should look like this:
aimed result
<categoryA>
<position>...</position>
<position>...</position>
...
</categoryA>
<categoryB>
<position>...</position>
<position>...</position>
...
</categoryB>
currently I have only managed to get the right results for the positions, the categoryA and B are 1 hierarchic layer higher than the positions. the positions should be nested in the categories. The categories can be referenced by let $y := $d/Bilanz/Aktiva/* (respectively $d$d/Bilanz/Aktiva/LangfristigesVermoegen and $d$d/Bilanz/Aktiva/KurzfristigesVermoegen).
Here is my query:
query
let $d := doc('http://etutor.dke.uni-linz.ac.at/etutor/XML?id=5001')/Bilanzen
let $a02 := $d/Bilanz[#jahr='2002']/Aktiva/*
let $a03 := $d/Bilanz[#jahr='2003']/Aktiva/*
for $n02 in $a02//* , $n03 in $a03//*
(:
where name($n02) = name($n03)
where node-name($n02) = node-name($n03)
:)
where name($n02) = name($n03)
return <position name="{node-name($n02)}">
<j2002>{data($n02/#summe)}</j2002>
<j2003>{data($n03/#summe)}</j2003>
<diff>{data($n03/#summe) - data($n02/#summe)}</diff>
</position>
xml
<Bilanzen>
<Bilanz jahr="2002">
<Aktiva>
<LangfristigesVermoegen>
<Sachanlagen summe="1486575.8"/>
<ImmateriellesVermoegen summe="67767.2"/>
<AssoziierteUnternehmen summe="190826.3"/>
<AndereBeteiligungen summe="507692.7"/>
<Uebrige summe="92916.4"/>
</LangfristigesVermoegen>
<KurzfristigesVermoegen>
<Vorraete summe="78830.9"/>
<Forderungen summe="198210.3"/>
<Finanzmittel summe="181102.0"/>
</KurzfristigesVermoegen>
</Aktiva>
<Passiva>
<Eigenkapital>
<Grundkapital summe="91072.4"/>
<Kapitalruecklagen summe="186789.5"/>
<Gewinnruecklagen summe="798176.2"/>
<Bewertungsruecklagen summe="-34922.4"/>
<Waehrungsumrechnung summe="0"/>
<EigeneAktien summe="0"/>
</Eigenkapital>
<AnteileGesellschafter summe="23613.1"/>
<LangfristigeVerb>
<Finanzverbindlichkeiten summe="680007.1"/>
<Steuern summe="36555.8"/>
<Rueckstellungen summe="429286.1"/>
<Baukostenzuschuesse summe="169246.0"/>
<Uebrige summe="36166.9"/>
</LangfristigeVerb>
<KurzfristigeVerb>
<Finanzverbindlichkeiten summe="14614.6"/>
<Steuern summe="65247.6"/>
<Lieferanten summe="94939.2"/>
<Rueckstellungen summe="123664.8"/>
<Uebrige summe="89464.8"/>
</KurzfristigeVerb>
</Passiva>
</Bilanz>
<Bilanz jahr="2003">
<Aktiva>
<LangfristigesVermoegen>
<Sachanlagen summe="1590313.7"/>
<ImmateriellesVermoegen summe="69693.2"/>
<AssoziierteUnternehmen summe="198224.7"/>
<AndereBeteiligungen summe="418489.3"/>
<Uebrige summe="104566.7"/>
</LangfristigesVermoegen>
<KurzfristigesVermoegen>
<Vorraete summe="20609.8"/>
<Forderungen summe="289458.5"/>
<Finanzmittel summe="302445.9"/>
</KurzfristigesVermoegen>
</Aktiva>
<Passiva>
<Eigenkapital>
<Grundkapital summe="91072.4"/>
<Kapitalruecklagen summe="186789.5"/>
<Gewinnruecklagen summe="875723.4"/>
<Bewertungsruecklagen summe="-15459.5"/>
<Waehrungsumrechnung summe="-633.7"/>
<EigeneAktien summe="0"/>
</Eigenkapital>
<AnteileGesellschafter summe="22669.8"/>
<LangfristigeVerb>
<Finanzverbindlichkeiten summe="733990.2"/>
<Steuern summe="68156.8"/>
<Rueckstellungen summe="395997.2"/>
<Baukostenzuschuesse summe="177338.5"/>
<Uebrige summe="38064.9"/>
</LangfristigeVerb>
<KurzfristigeVerb>
<Finanzverbindlichkeiten summe="6634.7"/>
<Steuern summe="97119.1"/>
<Lieferanten summe="89606.0"/>
<Rueckstellungen summe="128237.5"/>
<Uebrige summe="98495.2"/>
</KurzfristigeVerb>
</Passiva>
</Bilanz>
</Bilanzen>
I would really appreciate some help, i have no clue at all. Thank you.
If I understand you correctly, you want the information about LangfristigesVermoegen (and its children) to be grouped in the output under element categoryA, and the information about Kurzfristigesvermoegen to be grouped under categoryB.
So you will want first of all to do something to generate the categoryA and categoryB elements. For example,
let $d := doc(...)/Bilanzen
return (
<categoryA>{ ... children of category A here ... }</categoryA>,
<categoryB>{ ... children of category B here ... }</categoryB>
)
The positions in each category can be generated using code similar to what you've now got, except that instead of iterating over
for $n02 in $a02//* , $n03 in $a03//*
you will need to iterate over $a02[self::LangfristigesVermoegen]/* for category A, and over $a02[self::KurzfristigesVermoegen]/* for category B (and similarly, of course, for $n02 and $n03).
If the set of categories is not static and you just want to group things in the output using the same grouping elements present in the input, then you'll want an outer structure something like this:
for $assetclass1 in $anno2002/*
let $assetclass2 := $anno2003/*[name() = name($assetclass1)]
return
(element {name($assetclass1)} {
for $old in $assetclass1/*,
$new in $assetclass2/*
where name($old) eq name($new)
return <position name="{node-name($old)}">
<j2002>{data($old/#summe)}</j2002>
<j2003>{data($new/#summe)}</j2003>
<diff>{data($new/#summe) - data($old/#summe)}</diff>
</position>
})

Resources