xsl-list
[Top] [All Lists]

Re: Building select-clause dynamically with parameters

2002-12-11 01:04:28
Hi Marko,

The problem I still have with your stylesheet is that it does not work
(always) correctly. Also, it is probably not extremely efficient.

The xml file contains 2 books with some chapters and sections,
the text to be used as $query is hard coded in the xsl (in this case
'test'). The result is what I expect: a list of sections which
contain
the word (highlighted in html), and the list should contain all
parent
sections and chapters of this sections.

It works with ***this** xml file.  However, replace your second "book"
element with:

<book id="book2">
<title>Book 2</title>
<chapter id="chap21">
   <title>Chapter 1 of B2</title>
   <section id="sec211">
      <title>Section 1 of C1 of B2</title>
      <para>some text here</para>
      <section id="sec2111">
         <title>Subsection 1 of S1 of C1 of B2</title>
         <para>nothing</para>
      </section>
      <section id="sec2112">
         <title>Subsection 2 of S1 of C1 of B2</title><para>test</para>
      </section>
   </section>
   <section id="sec221">
      <title>Section 2 of C1 of B2</title>
      <para>something else</para>
   </section>
</chapter>
</book>

and define $searchtext as follows:
  
   <xsl:variable name="searchtext" select="'B2test'"/>


The result of applying the transformation (as displayed by the browser)
is:

"Query: B2test

Book 1

Book 2

   1  Chapter 1 of B2
   1.1  Section 1 of C1 of B2
   1.1.2  Subsection 2 of S1 of C1 of B2"



Now, the word "B2test" is not contained in any single text node.

I think that this is a wrong result.

Even if we define the search in such a way so that a result as the
above is considered OK, this expression (contained 4 times in your
code:

contains(descendant-or-self::*,$searchtext)

is equivalent to the much more obvious and not misleading:

contains(., $searchtext)

and the former would be performed much more inefficiently.

The question for me is how to pass an unknown number of words to
the stylesheet and how to build the select-clause dynamically. For
now
it is limited to one word, but I need something like "not(word1) and
word2"
or "word1 or (word2 and word3)".

I don't think this code should be further complicated, before
correcting its current problem.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL




"Marko Petersen" <lg002237(_at_)rzserv2(_dot_)fhnon(_dot_)de> wrote in message
news:5(_dot_)1(_dot_)1(_dot_)6(_dot_)0(_dot_)20021211021133(_dot_)00b9f308(_at_)rzserv2(_dot_)fhnon(_dot_)de(_dot_)(_dot_)(_dot_)
Hi,

to explain it in more detail I uploaded an example xml and xsl
(I don't want to post it all to the list) with result html to a
server:
http://digipub.fhnon.de/~mpetersen/xsl/

The xml file contains 2 books with some chapters and sections,
the text to be used as $query is hard coded in the xsl (in this case
'test'). The result is what I expect: a list of sections which
contain
the word (highlighted in html), and the list should contain all
parent
sections and chapters of this sections.

The question for me is how to pass an unknown number of words to
the stylesheet and how to build the select-clause dynamically. For
now
it is limited to one word, but I need something like "not(word1) and
word2"
or "word1 or (word2 and word3)".

Thanks for your help and greetings,

Marko

At 13:07 10.12.2002 -0800, you wrote:
Probably you think that the following applies the appropriate
templates
to ***all*** of the set of the a "chapter" node and its descendents,
the string value of which contains the value of $query?

    <xsl:template match="/">
      <xsl:apply-templates
select="chapter[contains(descendant-or-self::*,$query)]"/>
    </xsl:template>

This is wrong. The above code will apply a template only to every
"chapter" node, the text of which contains that of $query -- not to
any
descendent of a "chapter", even if the descendent contains the text
of
$query.

At first it may seem that a "chapter" will be selected if one of its
descendents contains $query -- this may not be the case. A "chapter"
may be selected even if none of its descendents (including its own
children text nodes) contains $query. This will be the case, when
$query is "made up" by the concatenation of the text of several
descendents.

It seems to me that the code above does not express at all what you
wanted.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL




"Marko Petersen" <lg002237(_at_)rzserv2(_dot_)fhnon(_dot_)de> wrote in 
message
news:5(_dot_)1(_dot_)1(_dot_)6(_dot_)0(_dot_)20021210194812(_dot_)00bb66f0(_at_)rzserv2(_dot_)fhnon(_dot_)de(_dot_)(_dot_)(_dot_)
Hi,

I would like to pass some words into my XSL file which should be
used
to build an XPath query in xsl:apply-templates. For an example,
the
following
works, but only for one word:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform";

    <xsl:param name="query"/>

    <xsl:template match="/">
      <xsl:apply-templates
select="chapter[contains(descendant-or-self::*,$query)]"/>
    </xsl:template>

    <xsl:template match="chapter | section">
      <table>
        <tr>
          <td>&#160;</td>
          <td>Found <xsl:value-of select="title"/>
            <xsl:apply-templates
select="section[contains(descendant-or-self::*, $query)]"/>
          </td>
        </tr>
      </table>
    </xsl:template>

    </xsl:stylesheet>

I don't know how many words will be passed into the XSL file,
this
should
be flexible.
For example, If $query has the value "word1 word2", the only
chapters
and
sections that
should be selected by apply-templates are those which contain
word1
or
word2, I think
in this case need I something like:

      <xsl:apply-templates
select="chapter[contains(descendant-or-self::*,'word1') or

contains(descendant-or-self::*,'word2')]"/>

I tried to pass the whole string used by "select" as parameter,
but
it does
not work.

Another thing is that I also have words that should be excluded
and
that I
would like
to pass a value into the XSL file that should define if it is an
AND
or an
OR query to
build something like:

      <xsl:apply-templates
select="chapter[contains(descendant-or-self::*,'word1') and

contains(descendant-or-self::*,'word2')
and

not(contains(descendant-or-self::*,'word3'))]"/>

Has anyone an idea how to do something like this? Or is it a
better
solution to do this
with Java DOM?

Thanks for help and greetings,

Marko


__________________________________________________
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list