Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: XSL Test expression: please help

From: "George Bina" <george@---------.--->
To: NULL
Date: 7/13/2006 2:05:00 AM

Hi,

Then you just need a recursive template to calculate the showQuestion
value. To avoid infinite recursion a soFar parameter is added that
accumulates questions processed so far.

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="tr" match="Trigger" use="QuestionID"/>
  <xsl:key name="q" match="Question" use="QuestionID"/>
  <xsl:template match="/*">
    <xsl:copy>
      <xsl:for-each select="Question">
        <xsl:variable name="triggers" select="key('tr', QuestionID)"/>
        <xsl:variable name="showQuestion">
          <xsl:call-template name="showQuestion">
            <xsl:with-param name="question" select="."/>
            <xsl:with-param name="triggers" select="$triggers"/>
          </xsl:call-template>
        </xsl:variable>
        <xsl:if test="string-length($showQuestion)>0">
          <xsl:copy-of select="."/>
        </xsl:if>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <xsl:template name="showQuestion">
    <!-- The current question -->
    <xsl:param name="question"/>
    <!-- The triggers for this question -->
    <xsl:param name="triggers"/>
    <!-- A string containing question IDs already processed -->
    <xsl:param name="soFar" select="''"/>
    <xsl:choose>
      <!-- No triggers, return yes -->
      <xsl:when test="count($triggers)=0">yes</xsl:when>
      <xsl:otherwise>
        <!-- itterate triggers -->
        <xsl:for-each select="$triggers">
          <!-- If the trigger condition holds -->
          <xsl:if test="ParentValue=key('q',
ParentQuestionID)/CurrentValue">
            <xsl:choose>
              <!-- If we already looked at the parent question return
yes -->
              <xsl:when test="contains($soFar,
ParentQuestionID)">yes</xsl:when>
              <!-- Otherwise check also the parent question, adding the
current question in the soFar
              variable to avoid infinite recoursion if we have cycles
-->
              <xsl:otherwise>
                <xsl:call-template name="showQuestion">
                  <xsl:with-param name="soFar" select="concat($soFar,
'*', $question/QuestionID)"/>
                  <xsl:with-param name="question" select="key('q',
ParentQuestionID)"/>
                  <xsl:with-param name="triggers" select="key('tr',
ParentQuestionID)"/>
                </xsl:call-template>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:if>
        </xsl:for-each>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

Best Regards,
George
---------------------------------------------------------------------
George Cristian Bina
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
www.---.com


Moskie wrote:
> Time to add a layer of complexity: recursion.
>
> Is there a way to not only check to make sure that the ParentQuestion
> is the proper value, but also check the all its ancestor questions
> (i.e. the ParentQuestion of the ParentQuestion, so forth and so on)?
>
> Moskie wrote:
> > Thanks, George! That seems to do the trick.
> >
> > I guess I'm fairly new to XSL, so the way you're setting the
> > showQuestion variable is new to me. Thanks for the tip.
> >
> >
> > Moskie
> >
> > George Bina wrote:
> > > Hi,
> > >
> > > You need to iterate on the triggers for a questions and check each
> > > trigger condition:
> > >
> > > <xsl:stylesheet version="1.0"
> > >   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> > >   <xsl:key name="tr" match="Trigger" use="QuestionID"/>
> > >   <xsl:key name="q" match="Question" use="QuestionID"/>
> > >   <xsl:template match="/*">
> > >     <xsl:copy>
> > >       <xsl:for-each select="Question">
> > >         <xsl:variable name="triggers" select="key('tr', QuestionID)"/>
> > >         <xsl:variable name="showQuestion">
> > >           <xsl:choose>
> > >             <xsl:when test="count($triggers)=0">yes</xsl:when>
> > >             <xsl:otherwise>
> > >               <xsl:for-each select="$triggers">
> > >                 <xsl:if
> > > test="ParentValue=key('q',ParentQuestionID)/CurrentValue">yes</xsl:if>
> > >               </xsl:for-each>
> > >             </xsl:otherwise>
> > >           </xsl:choose>
> > >         </xsl:variable>
> > >         <xsl:if test="string-length($showQuestion)>0">
> > >           <xsl:copy-of select="."/>
> > >         </xsl:if>
> > >       </xsl:for-each>
> > >     </xsl:copy>
> > >   </xsl:template>
> > > </xsl:stylesheet>
> > >
> > > Best Regards,
> > > George
> > > ---------------------------------------------------------------------
> > > George Cristian Bina
> > > <oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
> > > www.---.com
> > >
> > >
> > > moskie@g... wrote:
> > > > I have some XML representing survey questions and answers, along with
> > > > "trigger" definitions that represent a signal for when certain
> > > > questions should be displayed. Here's a stripped down example:
> > > >
> > > > <Question>
> > > >      <QuestionID>1</QuestionID>
> > > >      <CurrentValue>0</CurrentValue>
> > > > </Question>
> > > > <Question>
> > > >      <QuestionID>2</QuestoinID>
> > > >      <CurrentValue>1</CurrentValue>
> > > > </Question>
> > > > <Question>
> > > >      <QuestionID>3</QuestionID>
> > > >      <CurrentValue>0</CurrentValue>
> > > > </Question>
> > > >
> > > > <Trigger>
> > > >      <QuestionID>3</QuestionID>
> > > >      <ParentQuestionID>1</ParentQuestionID>
> > > >      <ParentValue>0</ParentValue>
> > > > </Trigger>
> > > > <Trigger>
> > > >      <QuestionID>3</QuestionID>
> > > >      <ParentQuestionID>2</ParentQuestionID>
> > > >      <ParentValue>0</ParentValue>
> > > > </Trigger>
> > > >
> > > > Basically, those triggers say that Question 3 should be displayed when
> > > > either Question 1 has a value of 0, or when Question 2 has a value of
> > > > 0. I plan to loop through each question, then run a test expression
> > > > that will determine whether that particular question gets displayed.
> > > >
> > > > First, the easy part:I test to see if there are no triggers for a
> > > > question, meaning that the question should always be displayed:
> > > >
> > > >      not(../Trigger[QuestionID = current()/QuestionID])
> > > >
> > > > The other part is where I'm stuck: testing to see if any of the
> > > > triggers' conditions have been met. This is what I have so far:
> > > >
> > > > or
> > > > ../Question[QuestionID = ../Trigger[QuestionID =
> > > > current()/QuestionID]/ParentQuestionID]/CurrentValue =
> > > > ../Trigger[QuestionID = current()/QuestionID]/ParentValue
> > > >
> > > > However, that just compares the set of CurrentValues of ParentQuestions
> > > > with the set of ParentValues from the all the Trigger nodes.... but
> > > > doesn't correlate the ParentQuestion and ParentAnswers together...
> > > >
> > > > Can anyone help me out in getting this expression to work?



transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent