0

I have a collection of two XML files (tagged according to TEI standard and containing lots of <entry> elements) in an eXist database. I'm looping through the file with a FLWOR routine, looking for the search term the user typed in a form ($searchterm) and returning the contents of certain elements. So far so good. I now would like to add another thing, but I don't know how to do that:

I would like to count how many <entry> had $searchterm in <form type="hyperlemma"> and print it instead of xxx. If $searchterm equals "ангелъ", the number would be "3". As I need to print that information before I loop through the collection, I have no clue what I need to do.

Could anyone help? As I'm still new to XQuery, my code probably isn't very pretty, so any hints that help me to improve it are much appreciated, too!

My XQuery:

xquery version "3.0";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare option exist:serialize "method=xhtml media-type=text/html";
declare variable $searchphrase := request:get-parameter("searchphrase", ());
declare variable $collection_path := "/db/apps/ex02/data";
<html>
<head>
<meta HTTP-EQUIV="Content-Type" content="text/html; charset=UTF-8"/>
<title>{$page-title}</title>
</head>
<body>
<h1>{$page-title}</h1>
<h2>Results</h2>
<p>Your input: "{$searchphrase}"</p>
<h3>Found xxx entries</h3>
   {
    for $file in collection($collection_path),
        $hyperlemma in $file/(descendant::tei:entry | descendant::tei:cit)/tei:form[@type='hyperlemma']/tei:orth [ft:query(., $searchphrase)]
        let $title := $hyperlemma/ancestor::*/tei:head
        let $entry_number := $hyperlemma/ancestor::tei:entry[1]/@xml:id
        let $lemma := $hyperlemma/ancestor::tei:entry/tei:form[@type='lemma']/tei:orth
    return
        <div>
        {string($title)} ({data($entry_number)}):<br/>
        <strong><font color="red">{string($lemma)}</font></strong><br/>
        {
            for $counterpart in $hyperlemma/ancestor::tei:entry/(tei:form[@type='lemma'] | tei:form[@type='variant'])/tei:cit/tei:form[@type='lemma']/tei:orth
            return
            <font color="green">&#160;&#160;&#160;&#160;{string($counterpart)}<br/></font>
        }
        </div>
}
</body>

These are snippets of the two XML files:

(A)

...
<text>
<head>Euch.</head>
<entry xml:id="pen-26">
    <form type="hyperlemma" xml:lang="grc">
        <orth>ἄγγελος</orth>
    </form>
    <form type="lemma" xml:lang="grc">
        <orth>ἄγγελος</orth>
        <cit type="counterpart" xml:lang="cu">
            <form type="hyperlemma" xml:lang="cu">
                <orth>ангелъ</orth>
            </form>
            <form type="lemma" xml:lang="cu">
                <orth>аньꙉелъ</orth>
            </form>
        </cit>
    </form>
</entry>
<entry xml:id="pen-336">
    <form type="hyperlemma" xml:lang="grc">
        <orth>ἀρχάγγελος</orth>
    </form>
    <form type="lemma" xml:lang="grc">
        <orth>ἀρχάγγελος</orth>
        <cit type="counterpart" xml:lang="cu">
            <form type="hyperlemma" xml:lang="cu">
                <orth>ангелъ</orth>
            </form>
            <form type="lemma" xml:lang="cu">
                <orth>аньꙉелъ</orth>
            </form>
        </cit>
    </form>
</entry>
</text>
...

(B)

...
<text>
<head>Syn.Tr. [1]</head>
<entry xml:id="tas-12">
<form type="hyperlemma" xml:lang="grc">
    <orth>ἄγγελος</orth>
</form>
<form type="lemma" xml:lang="grc">
    <orth>ἄγγελος</orth>
    <cit type="counterpart" xml:lang="cu">
        <form type="hyperlemma" xml:lang="cu">
            <orth>ангелъ</orth>
        </form>
        <form type="lemma" xml:lang="cu">
            <orth>ангєлъ</orth>
        </form>
    </cit>
    <cit type="counterpart" xml:lang="cu">
        <form type="hyperlemma" xml:lang="cu">
            <orth>вѣстьникъ</orth>
        </form>
        <form type="lemma" xml:lang="cu">
            <orth>вѣстьникъ</orth>
        </form>
    </cit>
</form>
</entry>
</text>
smo
  • 89
  • 8

1 Answers1

1

You just need to re-organise the query and HTML output slightly so that you perform the query before you want to output the number of results and results display. You can call fn:count on the results to get the number of results. However note, here we have package twice as many things into $results sequence, so we then divide it by 2. For example:

xquery version "3.0";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare option exist:serialize "method=xhtml media-type=text/html";
declare variable $page-title := "SlaVaComp-DB";
declare variable $searchphrase := request:get-parameter("searchphrase", ());
declare variable $collection_path := "/db/apps/ex02/data";
<html>
<head>
<meta HTTP-EQUIV="Content-Type" content="text/html; charset=UTF-8"/>
<title>{$page-title}</title>
</head>
<body>
<h1>{$page-title}</h1>
{
    let $results := 
        for 
            $file in collection($collection_path),
            $hyperlemma in $file/(descendant::tei:entry | descendant::tei:cit)/tei:form[@type='hyperlemma']/tei:orth [ft:query(., $searchphrase)]
        return
            ($file, $hyperlemma)
    return
        let $count := count($results) 
        let $offsets :=
            for $i in (0 to ($count div 2) cast as xs:integer - (if($count mod 2 eq 0)then 1 else 0)) 
            return
                2 * $i + 1
        return
        <div>
            <h2>Results</h2>
            <p>Your input: "{$searchphrase}"</p>
            <h3>Found {$count div 2} entries</h3>
            {
                for $offset in $offsets
                let $hyperlemma := $results[$offset + 1]
                let $title := $hyperlemma/ancestor::*/tei:head
                let $entry_number := $hyperlemma/ancestor::tei:entry[1]/@xml:id
                let $lemma := $hyperlemma/ancestor::tei:entry/tei:form[@type='lemma']/tei:orth
                return
                    <div>
                    {string($title)} ({data($entry_number)}):<br/>
                    <strong><font color="red">{string($lemma)}</font></strong><br/>
                    {
                        for $counterpart in $hyperlemma/ancestor::tei:entry/(tei:form[@type='lemma'] | tei:form[@type='variant'])/tei:cit/tei:form[@type='lemma']/tei:orth
                        return
                        <font color="green">&#160;&#160;&#160;&#160;{string($counterpart)}<br/></font>
                    }
                    </div>
            }
        </div>
}
</body>

The query above is somewhat complex as we pack both $file and $hyperlemma into a sequence, where the odd numbered offsets are the file and the even numbered offsets are the hyperlemma.

I notice though that you don't use the $file in your results, if you don't need it then your query could be much simplified to:

xquery version "3.0";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare option exist:serialize "method=xhtml media-type=text/html";
declare variable $page-title := "SlaVaComp-DB";
declare variable $searchphrase := request:get-parameter("searchphrase", ());
declare variable $collection_path := "/db/apps/ex02/data";
<html>
<head>
<meta HTTP-EQUIV="Content-Type" content="text/html; charset=UTF-8"/>
<title>{$page-title}</title>
</head>
<body>
<h1>{$page-title}</h1>
{
    let $hyperlemmas := collection($collection_path)/(descendant::tei:entry | descendant::tei:cit)/tei:form[@type='hyperlemma']/tei:orth [ft:query(., $searchphrase)]
    return
        <div>
            <h2>Results</h2>
            <p>Your input: "{$searchphrase}"</p>
            <h3>Found {count($hyperlemmas)} entries</h3>
            {
                for $hyperlemma in $hyperlemmas
                let $title := $hyperlemma/ancestor::*/tei:head
                let $entry_number := $hyperlemma/ancestor::tei:entry[1]/@xml:id
                let $lemma := $hyperlemma/ancestor::tei:entry/tei:form[@type='lemma']/tei:orth
                return
                    <div>
                    {string($title)} ({data($entry_number)}):<br/>
                    <strong><font color="red">{string($lemma)}</font></strong><br/>
                    {
                        for $counterpart in $hyperlemma/ancestor::tei:entry/(tei:form[@type='lemma'] | tei:form[@type='variant'])/tei:cit/tei:form[@type='lemma']/tei:orth
                        return
                        <font color="green">&#160;&#160;&#160;&#160;{string($counterpart)}<br/></font>
                    }
                    </div>
            }
        </div>
}
</body>

You might also be interested to read about KWIC if you want to highlight where various keyword searches matched in the text: http://www.exist-db.org/exist/apps/doc/kwic.xml

adamretter
  • 3,885
  • 2
  • 23
  • 43
  • Thank you very much! But unfortunately, it doesn't work yet. I tried to integrate your piece of code into my XQuery document, but eXide now throws two warnings ("tei: unused namespace prefix" and "$results: unused variable") and and an error: "hyperlemma: unused variable". I noticed that in your second line, you refer to $file, but $file is not set anywhere in your code (it was in my snippet). Does that mean anything? Sorry to bother again... – smo May 12 '15 at 15:18
  • Ah right whoops I pasted the wrong stage of my code, I have updated my answer. I hope that makes more sense. – adamretter May 12 '15 at 17:32
  • It works like a charm now! I will opt for version two, which does exactly what I was looking for. If I should ever need a more complex solution like the first one, I already have it - thanks to you! Thank you very much for taking the time to give a detailed answer! – smo May 13 '15 at 14:46