There are several options here.

   o Return sequences of sequences:

( author, title, abstract, journal, author, title, abstract, ... )

     This keeps everything as simple strings but it's
     brittle.  If you want to add date, for example, you
     need to make sure all the relevant code knows that
     there are now five elements per group rather than four.

   o Return encoded strings:

( "author/title/abstract/journal", "author/title/abstract/ journal", ... )

     This is awkward and can also be tricky if the magic
     separator character can occur in the text.  Somewhat
     less brittle but clumsy.

   o Return a constructed node:

        <journal-info>
            <author>Prof. Chalkdust<author>
            ...
        </journal-info>

     This requires an XML parser to work reliably,
     unless you want to do some regular expression
     hackery (which is brittle).


   But let me refer you to the big picture here.  We're
talking about JSP pages.  JSPs are markup containers
with callouts to code that can generate more markup.

   Separation of concerns is a good thing.  But beware
of artificial distinctions.  You may think you're
following good design principles by separating query
and markup like this:

    <xq:execute var="results">
        <xq:query>
            define variable $term as xs:string external

            for $i in cts:search(doc()//article-title,$term) [1 to 15]
            return $i/root()
        </xq:query>
<xq:variable localname="term" type="xs:string" value="$ {param.query}"/>
    </xq:execute>

    <ol>
    <c:forEach var="item" items="${results.items}">
        <x:parse xml="${item.string}" var="art" scope="session" />
        <li>
            <x:out select="$art//journal-id" />
        </li>
    </c:forEach>
    </ol>

   But why are you doing this?  Both the XQuery and the
JSTL tags are right there on the same page.  The query is
a part of the page, it's as easily modified as is the
JSTL code.  You've written a single "program" in two
languages.  Is this really separation of concerns?  The
query is captive to the markup.  It would only be true
separation if the query were defined elsewhere and was
re-usable in other contexts.

   Why not just do it all in XQuery, where it's simple and
very efficient?  As long as the query is right there in
the JSP you're not really gaining much by adding gratuitous
complexity.  This:

    <xq:execute var="results">
        <xq:query>
            define variable $term as xs:string external

            <ol>{
for $i in cts:search(doc()//article-title,$term) [1 to 15]
                return <li>{ fn:string($i/root()//journal-id) }</li>
            }</ol>
        </xq:query>
<xq:variable localname="term" type="xs:string" value="$ {param.query}"/>
    </xq:execute>

   Is more compact and more cohesive than the example
above.  If you need to change something, it's all right
there in front of you.

   If you're leveraging some generic query code, you
can still keep it simple by further querying and/or
decorating the result:

    <xq:execute var="results">
        <xq:query>
            import ...
            define variable $term as xs:string external

            <ol>{
                for $i in query-journals-by-term ($term)
                   return <li>{ fn:string($i//journal-id) }</li>
            }</ol>
        </xq:query>
<xq:variable localname="term" type="xs:string" value="$ {param.query}"/>
    </xq:execute>

   This works fine if you can use XHTML.  If you need
to output HTML (which may not be well-formed XML) you
can do the decoration in the JSP:

    <xq:execute>
        <xq:query>
            import ...
            define variable $term as xs:string external

            for $i in query-journals-by-term ($term)
                return fn:string($i//journal-id)
        </xq:query>
<xq:variable localname="term" type="xs:string" value="$ {param.query}"/>

        <ol>
        <xq:result>
            <li><xq:streamItem/></li>
        </xq:result>
        </ol>
    </xq:execute>


   There are several ways to skin a cat, but you don't
need to use them all.  Mark Logic is the power tool, let
it do as much for you as possible.


On Apr 4, 2007, at 2:14 PM, Alan Darnell wrote:

Thanks for this. The alternative model you describe works great if I'm returning a single value from Mark Logic. But what if I want to get back multiple values from Mark Logic for each document (e.g. author, title, abstract, journal title) so I can display these to the user. Can I store these in a structure in the "results" variable so I can pull each of these out when I iterate over results? Or is this something better done in a servlet with the results stored in a collection of beans and accessed from the JSP page? What are good models for using Mark Logic in a J2EE context.

Alan


On 4-Apr-07, at 4:41 PM, Ron Hitchens wrote:


   I tinkered with this for a while and got it
working.  There are a couple of issues to address.

   The reason for the exception you're seeing is
that the JSTL jars in the Mark Logic JSP bundle
are old and are referring to an external XPath
library that isn't included.  Updating the JSTL
jars (jstl.jar and standard.jar) to the latest
release should make the XML tags work as expected.
I will update the JSP bundle as soon as I can.

[http://jakarta.apache.org/site/downloads/downloads_taglibs- standard.cgi]


   There are a couple of other things I want to
discuss about your example.  The first is an
important security issue.  You're building up
your query by inserting a string obtained from
a user-supplied parameter.  This leaves you open
to code injection attacks and/or spurious failures
caused by garbled input.

   Rather than this:

    <xq:execute var="results">
        <xq:query>
for $i in cts:search(doc()//article-title,"$ {param.query}") [1 to 15]
            return $i/root()
        </xq:query>
    </xq:execute>

   Pass the user-supplied value as an external variable:

    <xq:execute var="results">
        <xq:query>
            define variable $term as xs:string external

for $i in cts:search(doc()//article-title,$term) [1 to 15]
            return $i/root()
        </xq:query>
<xq:variable localname="term" type="xs:string" value="$ {param.query}"/>
    </xq:execute>


   But more significantly, unless you really, really
need to use the JSTL XML tags for some reason I recommend
not using them at all and doing all the XML and XPath
work in your Mark Logic queries.  For example, here is
a modification that gives the same result using only
the core JSTL tags:

    <xq:execute var="results">
        <xq:query>
            define variable $term as xs:string external

for $i in cts:search(doc()//article-title,$term) [1 to 15]
                return fn:string($i/root()//journal-id)
        </xq:query>
<xq:variable localname="term" type="xs:string" value="$ {param.query}"/>
    </xq:execute>

    <ol>

    <c:forEach var="item" items="${results.items}">
        <li>
            <c:out value="${item.string}" escapeXml="true"/>
        </li>
    </c:forEach>

    </ol>

   This query returns only the journal IDs rather than the full
documents, which is far more efficient for the JSP container.

   Another way to do this, without using any JSTL tags
at all, is to use the looping xq:result tag (note that the
xq:execute tag no longer has a "var" attribute):

    <xq:execute>
        <xq:query>
            define variable $term as xs:string external

for $i in cts:search(doc()//article-title,$term) [1 to 15]
            return fn:string($i/root()//journal-id)
        </xq:query>
<xq:variable localname="term" type="xs:string" value="$ {param.query}"/>

        <h2>Search results</h2>
        <ol>
        <xq:result>
            <li><xq:streamItem/></li>
        </xq:result>
        </ol>
    </xq:execute>

_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general

---
Ron Hitchens [EMAIL PROTECTED]  650-655-2351




Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general

Reply via email to