質問

I'm trying to write an Xquery which has 2 parts:

The first part is a function in Xquery to compute the number of students for each class element. the input of the function should be a class element and the output is the number of students who took that class.

At the second part I want the list of courses which had at least one student (for finding the number of students for each course I have to use the function from the first part).

This is how the input xml file looks like: in the input file we have 3 different elements: Student, Class, and Course, which are related together.

    <?xml version="1.0" ?>
    <Report Date="1999-12-02">
     <Students>
     <Student StudId="s11">
     <Name><First>John</First><Last>Doe</Last></Name>
     <Status>U2</Status>
     <CrsTaken CrsCode="CS308" Semester="F1997"/> 
     <CrsTaken CrsCode="MAT123" Semester="F1997"/> 
     </Student>
     <Student StudId="s66">
     <Name><First>Joe</First><Last>Public</Last></Name>
     <Status>U2</Status> 
     <CrsTaken CrsCode="MAT123" Semester="F1997"/> 
     </Student>
     </Students>
     <Classes>
     <Class>
     <CrsCode>CS308</CrsCode><Semester>F1997</Semester>
     <ClassRoster Members="s11"/>
     </Class>
     <Class>
     <CrsCode>MAT123</CrsCode><Semester>F1997</Semester>
     <ClassRoster Members="s11 s66"/>
     </Class>
    </Classes>
     <Courses>
     <Course CrsCode="CS308">
     <CrsName>Software Engineering</CrsName>
     </Course> 
     <Course CrsCode="MAT123">
     <CrsName>ALgebra</CrsName>
     </Course>
     </Courses>
    </Report>

And this is the code I've done. I wrote a function which has an element(class) as input and will return an integer as number of students. I also tried to call the function for the second part.which call the function to find the classes which has more than one member. But my query doesn't return anything. it seems there is small mistake. should I use data unction instead of text or something else? And this is the code I've done. I wrote a function which has an element(class) as input and will return an integer as number of students. I also tried to call the function for the second part.which call the function to find the classes which has more than one member. But my query doesn't return anything. it seems there is small mistake. should I use data unction instead of text or something else?

    declare function local:numStudents($e as element())as xs:integer
    {
      count(
        for $s in doc('data.xml')//Student
        let $T:=$e[CrsCode/text()=$s/CrsTaken/@CrsCode and Semester/text()=$s/CrsTaken/@Semester]
        where not(fn:empty($T))
        return $s
      )
    };

    <Courses>
     {for $co in doc('data.xml')//Course,
        $c in doc('data.xml')//Class
       where $co/@CrsCode=$c/CrsCode/text() and local:numStudents($c)>1
     return <course CrsCode="{$co/@CrsCode}" name="{$co/CrsName/text()}" />}
    </Courses> 

is there any help? I run this code in Altova Xml spy and t runs without any error but there is no output. it seems something for text is wrong.

役に立ちましたか?

解決

You may prefer to move the query from the where clause into a separate function, but this should work:

<Courses>{
  for $co in doc('data.xml')//Course
  let $code := $co/@CrsCode
  for $class in doc('data.xml')//Class[CrsCode = $code]
  let $sem := $class/Semester
  where exists(doc('data.xml')//Student/CrsTaken[@CrsCode = $code and @Semester = $sem])
  return <course CrsCode="{ $co/@CrsCode }" name="{ $co/CrsName }" />
}</Courses>

Generally, exists() should perform better than counting all of the students because the XQuery processor should stop counting after 1; however, this will not have much impact unless that data set is much larger.

Also, a note about text() (and data()): typically string() is what you want, and in many cases (like this example) values will be coerced into strings automatically. For more information, Evan Lenz has a very good blog on the topic:

https://developer.marklogic.com/blog/text-is-a-code-smell

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top