Struggling with XSLT processing of nested elements

≡放荡痞女 提交于 2020-02-08 08:35:01

问题


I am trying to process some XML that has nested elements into HTML where each processed element is within tags so that I can show and hide divs using JavaScript based on the user pressing a Next link. I am having problems because the tag for the parent is being placed after the for the 2 children. This is causing an issue because I cannot hide the parent to show the children.

here is the XML snippet I am starting with:

<mainProcedure>
   <proceduralStep id="pstp1">
      <para>Some text to display 1</para>
   </proceduralStep>
   <proceduralStep id="pstp2">
      <note>Warning Note to display</note>
      <para>Some text to display 2</para>
      <proceduralStep id="pstp21">
         <para>Nested procedural step 1</para>
      </proceduralStep>
      <proceduralStep id="pstp22">
         <para>Nested procedural step 2</para>
      </proceduralStep>
   </proceduralStep>
   <proceduralStep id="pstp3">
      <para>Some text to display 3</para>
   </proceduralStep>
</mainProcedural>

The can be nested. The way my current XSLT is processing this is that the tag for is placed after the closing for . I believe I need to flatten this structure when I output so the JavaScript showing and hiding of tags works properly. So instead of having:

<div id="pstp1">  Some text to display 1 
   NEXT (embeds JS to hide pstp1 and show pstp2)   
</div>
<div id="pstp2"> 
   NOTE: Warning Note to display
   Some text to display 1
      NEXT (embeds JS to hide pstp2 and show pstp21)   
   <div id="pstp21>Nested procedural step 1
      NEXT (embeds JS to hide pstp21 and show pstp22)   
   </div>
   <div id="pstp22>Nested procedural step 2
      NEXT (embeds JS to hid pstp22 and show pstp3)
   </div>
</div>
<div id="pstp3"> Some test to display 3 </div>

I believe in order to the show and hide div to work properly I need to flattened the output to:

<div id="pstp1">  
   Some text to display 1 
   NEXT (embeds JS to hide pstp1 and show pstp2)   
</div>
<div id="pstp2"> 
   NOTE: Warning Note to display
   Some text to display 1
   NEXT (embeds JS to hide pstp2 and show pstp21)   
</div>
<div id="pstp21>
   Nested procedural step 1
   NEXT (embeds JS to hide pstp21 and show pstp22)   
</div>
<div id="pstp22>
   Nested procedural step 2
   NEXT (embeds JS to hid pstp22 and show pstp3)
</div>
<div id="pstp3"> Some test to display 3 </div>

I cannot figure out how to do this. I have an in my XSLT so then this is invoked on the second element, the for the second element is showing up after the processing of the nested elements.

Here is the current XSLT template used to process the element. Please note that this is a work in progress and I may have complicated something that was not necessary. If there are any questions on the template and why I did something, please let me know.

<xsl:template match="proceduralStep">
    <xsl:choose>
       <!--  See if there is a child proceduralStep (or a nested proceduralStep) -->
       <xsl:when test="child::proceduralStep">
          <!-- procedrualStep contains a nested proceduralStep, count the precdeing siblings to help with numbering of steps -->
          <xsl:variable name="stepCounter" select="count(preceding-sibling::proceduralStep)+1" />
          <xsl:variable name="step_id" select="./@id" />              
          <xsl:variable name="nextRefId" select="child::proceduralStep/@id" />

          <xsl:choose>
             <xsl:when test="$stepCounter = 1">
                <div id="{$step_id}" style="display: block;">
                   Step <xsl:value-of select="$stepCounter" />
                   <xsl:text> </xsl:text>
                   <xsl:apply-templates /> 
                   <br/>
                   <div>
                      <a href="#{$nextRefId}" onclick="show_hide_div('{$step_id}','{$nextRefId}')">Next</a><br/>
                   </div>              
                </div>                
             </xsl:when>
             <xsl:otherwise>
                <div id="{$step_id}" style="display: none;">
                      Step <xsl:value-of select="$stepCounter" />
                      <xsl:text> </xsl:text>
                      <xsl:apply-templates />
                 </div>
              </xsl:otherwise>
          </xsl:choose>

       </xsl:when>
       <xsl:otherwise>
          <!-- <proceduralStep> element does not have any nested <proceduralStep> elements  -->

          <!-- Count the number of preceding <proceduralStep> elements  -->
          <xsl:variable name="stepCounter" select="count(preceding-sibling::proceduralStep)+1"/> 

          <!-- Get the current <proceduralStep> element's id  -->                     
          <xsl:variable name="step_id" select="./@id"/>

          <!-- Since the current <proceduralStep> does not have any children, get the following <proceduralStep> sibling id -->
          <xsl:variable name="nextRefId" select="following-sibling::proceduralStep/@id"/>

          <xsl:choose>
             <!-- If this is the first <proceduralStep> element create the <div>  -->
             <xsl:when test="$stepCounter = 1">

                <!-- first time encountering a step, check to see if it is the first nested <proceduralStep> -->
                <xsl:choose>
                   <xsl:when test="parent::proceduralStep">
                      <!-- add the Next button before we output the <proceduralStep> -->
                      <div>
                         <xsl:variable name="parentProcStepId" select="parent::proceduralStep/@id" />
                         <p>parentProcStepID: <xsl:value-of select="$parentProcStepId" /> </p>
                         <a href="#{$step_id}" onclick="show_hide_div('{$parentProcStepId}','{$step_id}')">Next</a><br/>
                      </div>

                      <div id="{$step_id}" style="display: none;">
                         Step <xsl:value-of select="$stepCounter" />
                         <xsl:text> </xsl:text>
                         <xsl:apply-templates />
                         <br/>
                         <div>
                            <a href="#{$nextRefId}" onclick="show_hide_div('{$step_id}','{$nextRefId}')">Next</a><br/>
                         </div>
                      </div>      
                   </xsl:when>
                   <xsl:otherwise>
                      <div id="{$step_id}" style="display: block;">
                         Step <xsl:value-of select="$stepCounter" />
                         <xsl:text> </xsl:text>
                         <xsl:apply-templates />
                         <br/>

                         <div>
                            <a href="#{$nextRefId}" onclick="show_hide_div('{$step_id}','{$nextRefId}')">Next</a><br/>
                         </div>
                      </div>
                      </xsl:otherwise>
                      </xsl:choose>


             </xsl:when>
              <xsl:otherwise>
                 <!-- do nothing -->
             </xsl:otherwise>
          </xsl:choose>      
       </xsl:otherwise>
   </xsl:choose>
</xsl:template>

Any idea how to help get this to work?

Thank you


回答1:


How about this way:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/*">
    <root>
        <xsl:apply-templates select="proceduralStep"/>
    </root>
</xsl:template>

<xsl:template match="proceduralStep">
    <div id="{@id}">
        <xsl:apply-templates select="note | para"/>
        <br/>   
        <xsl:text>NEXT( ... )</xsl:text>
    </div>
    <xsl:apply-templates select="proceduralStep"/>
</xsl:template>

<xsl:template match="note">
    <xsl:text>NOTE: </xsl:text>
    <xsl:value-of select="."/>
    <br/>   
</xsl:template>

</xsl:stylesheet>


来源:https://stackoverflow.com/questions/26974692/struggling-with-xslt-processing-of-nested-elements

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!