XSLT条件 - 如果节点A中的详细信息为true,则在节点B中显示详细信息

时间:2012-08-10 16:18:35

标签: xml xslt xpath

我需要帮助来放置一个有效的XSLT条件:在遍历问题节点的for-each循环中;如果节点A上的条件有效,则在节点B中显示详细信息 XML示例:

<Survey>
    <questions>
        <Number>1.0</Number>
        <Question>Was the show good?</Question>
        <Answer>Yes/No</Answer>
        <Details>N/A</Details>
    </questions>
    <questions>
        <Number>1.1</Number>
        <Question>Explain why</Question>
        <Answer>N/A</Answer>
        <Details>The actors were good</Details>
    </questions>
    <questions>
        <Number>2.0</Number>
        <Question>Was the food good?</Question>
        <Answer>Yes|No</Answer>
        <Details>N/A</Details>
    </questions>
    <questions>
        <Number>2.1</Number>
        <Question>Provide details</Question>
        <Answer>N/A</Answer>
        <Details>The pasta was too salty</Details>
    </questions>
</Survey>

我需要的是使用for-each的循环 仅当问题编号= 1.0且答案=“是”时,在问题编号1.1中显示详细信息 仅当问题编号= 2.0且答案='否'时,在问题编号2.1中显示详细信息

我已经尝试了所有方法,例如,如果,每个,选择/何时,但它没有奏效。 我检查了你的其他帖子,但找不到类似的东西。谢谢你,Tubi。

对不起,所以它应该是这样的:

    <Survey>     
        <questions>
            <Number>1.0</Number>
            <Question>Was the show good?</Question>
            <Answer>Yes</Answer>
            <Details>N/A</Details>     
    </questions>     
    <questions>
         <Number>1.1</Number>
         <Question>Explain why</Question>
         <Answer>N/A</Answer>         
         <Details>The actors were good</Details>
     </questions>     
     <questions>
         <Number>2.0</Number>
         <Question>Was the food good?</Question>         
         <Answer>Yes</Answer>
         <Details>N/A</Details>
     </questions>
     <questions>
         <Number>2.1</Number>
         <Question>Provide details</Question>
         <Answer>N/A</Answer>
         <Details>The pasta was too salty</Details>
     </questions>
 </Survey> 

以下是我的代码:(对不起,它实际上是某人的代码。我需要修改显示下一个问题的部分,当前一个问题被明确回答“是”或“否”时

<fo:table-body start-indent="0pt">
    <xsl:for-each select="../Survey">
        <xsl:for-each select="questions">
        <xsl:sort select="Number" data-type="number" order="ascending"/>
            <fo:table-row>
                <xsl:choose>
                    <xsl:when test="ends-with(Number,'0')">
                        <fo:table-cell border="solid 1pt gray" padding="1pt" display-align="center">
                       <fo:block text-align="right">
                                <xsl:for-each select="Number"> ...
                           </xsl:for-each>
                            </fo:block>
                        </fo:table-cell>
                        <fo:table-cell border="solid 1pt gray" padding="1pt" display-align="center">
                            <fo:block text-align="left">
                                <xsl:for-each select="Description"> ...
                                </xsl:for-each>
                            </fo:block>
                        </fo:table-cell>
                        <fo:table-cell border="solid 1pt gray" padding="1pt" display-align="center"> 
                            <fo:block text-align="left" color="blue">
                               <xsl:for-each select="Answer"> ...
                               </xsl:for-each>
                            </fo:block>
                        </fo:table-cell>                                   </xsl:when>  
                    <xsl:when test="Number='1.1'">
                        <xsl:if test="//questions/Number='1.0' and //questions/Answer='No'">
                           <fo:table-cell border="solid 1pt gray" padding="1pt" display-align="center">
                               <fo:block text-align="right">
                                    <xsl:for-each select="Number"> ...
                                    </xsl:for-each>
                               </fo:block>
                           </fo:table-cell>
                           <fo:table-cell border="solid 1pt gray" padding="1pt" display-align="center">
                               <fo:block text-align="left">
                                   <xsl:for-each select="Question">  .....
                                   </xsl:for-each>
                               </fo:block>
                           </fo:table-cell>
                           <fo:table-cell border="solid 1pt gray" padding="1pt" display-align="center"> 
                              <fo:block text-align="left" color="blue">  ....
                                   <xsl:for-each select="Details">
                                   </xsl:for-each>
                              </fo:block>
                           </fo:table-cell>                                      </xsl:if>  
                       </xsl:when>  
                       <xsl:otherwise>do something</xsl:otherwise>                        </xsl:choose>
               </fo:table-row>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
</fo:table-body>            

2 个答案:

答案 0 :(得分:2)

作为经验法则。如果您的代码包含大量重复内容,那么您做错了。 XSLT也不例外。

<!-- index followup questions (no zero after the dot) -->
<xsl:key 
  name="kFollowupQuestions"
  match="questions[number(substring-after(Number, '.')) != 0]" 
  use="number(substring-before(Number, '.'))"
/>

<!-- the <Survey> becomes the <fo:table-body> -->
<xsl:template match="Survey">
  <fo:table-body start-indent="0pt">
    <!-- only select main questions (with a zero after the dot) -->
    <xsl:apply-templates select="questions[number(substring-after(Number, '.')) = 0]">
      <xsl:sort select="Number" data-type="number" order="ascending" />
    </xsl:apply-templates>
  </fo:table-body>
</xsl:template>

<!-- each <questions> becomes a <fo:table-row> -->
<xsl:template match="questions">
  <xsl:variable name="qNum"   select="number(substring-before(Number, '.'))" />
  <xsl:variable name="subNum" select="number(substring-after(Number, '.'))" />
  <fo:table-row>
    <xsl:apply-templates select="Number" />
    <xsl:apply-templates select="Question" />
    <xsl:apply-templates select="Answer" />
    <xsl:apply-templates select="Details" />
  </fo:table-row>
  <!-- for main question answered with 'Yes', display followup-questions --> 
  <xsl:if test="Answer = 'Yes' and $subNum = 0">
    <xsl:apply-templates select="key('kFollowupQuestions', $qNum)">
      <xsl:sort select="Number" data-type="number" order="ascending" />
    </xsl:apply-templates>
  </xsl:if>
</xsl:template>

<!-- the <questions> children become <fo:table-cell>s -->
<xsl:template match="questions/*">
  <fo:table-cell border="solid 1pt gray" padding="1pt" display-align="center">
    <fo:block text-align="right">
      <xsl:value-of select="." /><!-- or whatever -->
    </fo:block>
  </fo:table-cell>
</xsl:template>

http://www.xmlplayground.com/K4VHM2

答案 1 :(得分:1)

我会改变你的

<xsl:when test="Number='1.1'">
   <xsl:if test="//questions/Number='1.0' and //questions/Answer='No'">

<xsl:when test="Number='1.1'">
   <xsl:if test="../questions[Number = '1.0']/Answer = 'No'">

假设您没有一般的方法可以知道,对于任何问题,您是否应该在“是”答案或“无答案”上显示更多详细信息,因此每个* .0都有一个单独的<xsl:when>案例问题

P.S。奇怪的是,XSL在每个<xsl:for-each select="Number">内使用<fo:block>等,因为您的示例输入中只有<Number><questions>子项。所有这一切都是改变上下文节点。也许意图是使用<xsl:apply-templates select="Number" />