xmlxqueryzorba

Each result on a new line XQuery


I know there is similar question asked but the solution given in that did not solve my issue. And since I have less reputation I am unable to comment on the same question page.

My XQuery code:

 <results>
    {
        for $p in
        (
        for $o in doc("mondial-3.0.xml") /mondial/organization
        where fn:count($o/members)
        order by fn:count($o/members) descending
        let $m := $o/members
        return <organization>
                <name> {$o/@name/string()} </name>
                <abbreviation> {$o/@abbrev/string()} </abbreviation>
                <num_members> {fn:count($o/members)} </num_members> 
                <country> {doc("mondial-3.0.xml")/mondial/country[@id=$m/@country]/@name/string()} </country>
           </organization>
        )[position() < 3]
        return $p
    }
    </results>

I am using Zorba as the XQuery engine for getting the output. The output which i am getting is correct, just that structure of my output is not the way I want it to be.

Currently all the countries are getting printed on the same line.

<country> Angola Argentina Bolivia.... </country>

But I want each new country to be on a new separate line.

<country> Angola </country>
<country> Argentina</country>
<country> Bolivia </country>

XML file:

https://raw.githubusercontent.com/kroell/hsrm-mi-2semester-markuplanguage/master/Abgabe2/Aufgabe2/mondial-3.0.xml


Solution

  • As you didn't provide example input, I could not provide a verified solution.

    The issue is that you create one element containing text nodes for all country names. Create multiple text nodes instead, for example using another flwor expression:

    <organization>
      <name> {$o/@name/string()} </name>
      <abbreviation> {$o/@abbrev/string()} </abbreviation>
      <num_members> {fn:count($o/members)} </num_members>
      {
        for $country in doc("mondial-3.0.xml")/mondial/country[@id=$m/@country]/@name/string()
        return <country>{ $country }</country>
      }
    </organization>
    

    If you've got support for XQuery 3.0, you can also go for element constructors in axis steps, having a more concise, implicit loop construction:

    <organization>
      <name> {$o/@name/string()} </name>
      <abbreviation> {$o/@abbrev/string()} </abbreviation>
      <num_members> {fn:count($o/members)} </num_members>
      {
        doc("mondial-3.0.xml")/mondial/country[@id=$m/@country]/@name/element country { data() }
      }
    </organization>
    

    One recommendation: Instead of <name> {$o/@name/string()} </name>, better go for <name>{ $o/@name/string() }</name> to prevent superfluous whitespace around the information inside the tag.