0
votes

First of all, I'm totally new in Xquery and I am sorry my problem is very stupid :/ .

This is just a part of my XML :

<books>
    <book id="b1">
      <title>Set theory and the continuum problem</title>
      <category>Mathematics</category>
      <location>
        <area>hall1</area>
        <case>1</case>
        <shelf>2</shelf>
      </location>
      <description>A lucid, elegant, and complete survey of set theory.</description>
      <history>
        <borrowed by="m4"/>
        <borrowed by="m2" until="2018-04-05"/>
      </history>
    </book>
    <book id="b2">
      <title>Computational Complexity</title>
      <isbn>978-0201-530-827</isbn>
      <category>Computer Science</category>
      <location>
        <area>hall1</area>
        <case>3</case>
        <shelf>3</shelf>
      </location>
      <description>.</description>
    </book>
    <book id="b3">
      <title>To mock a mockingbird</title>
      <isbn>1-292-09761-2</isbn>
      <category>Logic</category>
      <category>Mathematics</category>
      <location>
        <area>hall1</area>
        <case>1</case>
        <shelf>3</shelf>
      </location>
      <description>.</description>
     </book>
</books>
 <libraryArea floor="1" name="hall1">
    <bookcases>
      <woodenCase id="3" shelves="5"/>
      <woodenCase id="2" shelves="5"/>
      <steelCase id="1" shelves="5"/>
    </bookcases>
  </libraryArea>
  <libraryArea name="hall2">
    <bookcases>
      <lockedCase id="1" shelves="9"/>
      <steelCase id="4" shelves="3"/>
      <lockedCase id="3" shelves="2"/>
      <steelCase id="2" shelves="4"/>
    </bookcases>
  </libraryArea>
  <libraryArea name="hall3">
    <bookcases>
      <woodenCase id="2" shelves="3"/>
      <steelCase id="1" shelves="8"/>
    </bookcases>
  </libraryArea>
  <libraryArea name="archive">
    <bookcases>
      <lockedCase id="1" shelves="1"/>
    </bookcases>
  </libraryArea>
</library>

I want to list specific book titles in their own tags ''

Something like this:


<specialSteelCases>
   <area name="hall1">
     <steelCase id="1">
        <bookCount>2</bookCount>
        <book>Set theory and the continuum problem</book>
        <book>To mock a mockingbird</book>
        <shelves>5</shelves>
      </steelCase>
   </area>
</specialSteelCases>

But I get this, all book titles in just one book tag:

< book > Set theory and the continuum problemTo mock a mockingbird < / book >

Is there a way I can separate them apart, so each book title have their own

This is my Xquery:

<specialSteelCases>
{
for $a in //libraryArea
where $a/bookcases[count(woodenCase) > 1 ]
order by $a/@id
return
    <area name="{$a/@name}">
    {
        for $s in $a//bookcases/steelCase
        let $bbNew := (//books/book[location/case=$s/@id][location/area=$a/@name])
        return
           <steelCase id="{$s/@id}">
                <bookCount>***code***</bookCount>
                <book>{$bbNew/title/text()}</book>
                <shelves>***code**</shelves>
           </steelCase>
    }
    </area> 
}
</specialSteelCases>
1
Which XQuery processor, which XQuery version do you use? It looks like a grouping problem which in XQuery 3 and later is best solved using the group-by clause of a FLOWR expression. - Martin Honnen
@MartinHonnen XQuery 1.0 ..... Is it possible to nest another for-loop inside <steelCase> ? - Vedran D

1 Answers

0
votes

Use a let clause to select the relevant books and then count them and additionally with a nested for expression output the titles:

<specialSteelCases>
{
for $a in //libraryArea
where $a/bookcases[count(woodenCase) > 1 ]
order by $a/@id
return
    <area name="{$a/@name}">
    {
        let $books := //books/book[location/case=$a//bookcases/steelCase/@id][location/area=$a/@name]
        return
           <steelCase id="{$a//bookcases/steelCase/@id}">
                <bookCount>{count($books)}</bookCount>
                {
                    for $title in $books/title
                    return
                        <book>{data($title)}</book>
                }
           </steelCase>
    }
    </area> 
}
</specialSteelCases>

https://xqueryfiddle.liberty-development.net/jyyiVhw/1

If you can move to XQuery 3 and simply grouping:

for $book in //books/book
group by $case := //library/libraryArea[@name = $book/location/area]/bookcases/*[@id = $book/location/case]/local-name()
return
    element {$case } {
        <bookCount>{count($book)}</bookCount>
        ,
        $book/title ! <book>{data()}</book>
    }

https://xqueryfiddle.liberty-development.net/jyyiVhw