简体   繁体   中英

How to use variables in xsl:for-each but create the output later?

I'm struggling to get the output to display as required.

I run an xslt 1.0 file that parses every 5 seconds a xml file that contains statistical information. every 15 minutes we get an additional file to parse which is pulled in as external source. The parsing is fine but displaying the information fails miserably. This is the section that creates the output:

<td>
  <table cellSpacing="0" border="1" cellPadding="2" style="background-color:lightblue;color:green;font-size:80%;">
    <xsl:for-each select="/DialStats/Countries">
      <!-- @Country = 15 min 2nd XML file / $Country = 5 sec prim XML file-->
      <xsl:if test="@Country = $Country">
          <xsl:for-each select="./Products">
            <!-- @Product = 15 min 2nd XML file / $Product = 5 sec prim XML file-->
            <xsl:if test="@Product = $Product">
              <xsl:for-each select="Dispositions">
                <xsl:variable name="TSB">
                  <xsl:if test="@Result = 'Tour / Sale / Booking'">
                    <xsl:value-of select="@Count"/>
                   </xsl:if>
                 </xsl:variable>
<!-- // set multiple variables:  -->
                 <xsl:variable name="ITF">
                   <xsl:if test="@Result = 'Internal Transfer'">
                     <xsl:value-of select="@Count"/>
                   </xsl:if>
                 </xsl:variable>

<!-- // Now generate the output:  -->
                 <xsl:choose>
                   <xsl:when test="string-length($TSB)=0 and string-length($NoAgent)=0">
                     <!-- Don't do anything -->
                   </xsl:when>  
                   <xsl:when test="string-length($TSB)!=0 and string-length($NoAgent)=0">
                     <tr>
                       <td>
                         <xsl:value-of select="$TSB"/>
                       </td>
                       <td> - </td>
                       <td>TSB</td>
                       <td>. .</td>
                       <td colspan="3"></td>
                     </tr>
                   </xsl:when>
                   <xsl:when test="string-length($TSB)=0 and string-length($NoAgent)!=0">
                     <tr>
                       <td colspan="3"></td>
                       <td>. .</td>
                       <td>
                         <xsl:value-of select="$NoAgent"/>
                       </td>
                       <td>-</td>
                       <td>No Agent</td>
                     </tr>
                   </xsl:when>
                   <xsl:otherwise>
                     <tr>
                       <td>
                         <xsl:value-of select="$TSB"/>
                       </td>
                       <td> - </td>
                       <td>TSB</td>
                       <td>. .</td>
                       <td>
                         <xsl:value-of select="$NoAgent"/>
                       </td>
                       <td>-</td>
                       <td>No Agent</td>
                     </tr>
                   </xsl:otherwise>
                 </xsl:choose>
<!-- // Generate more of the output:  -->
<!-- // Last section  -->
                  <xsl:choose>
                    <xsl:when test="string-length($OTH)=0">
                      <!-- Don't do anything -->
                    </xsl:when>
                    <xsl:when test="string-length($OTH)!=0">
                      <tr>
                        <td>
                          <xsl:value-of select="$OTH"/>
                        </td>
                        <td>-</td>
                        <td>OTH</td>
                        <td>. .</td>
                        <td colspan="3"></td>
                      </tr>
                    </xsl:when>
                    <xsl:otherwise>
                      <!-- Nothing to do -->
                    </xsl:otherwise>
                  </xsl:choose>
               </xsl:for-each>
             </xsl:if>
           </xsl:for-each>
         </xsl:if>
       </xsl:for-each>
   </table>
 </td>

This generates a table however due to how the XML file contains information it is not consistently in the same spot, it might not be there at all. I want the information to show on the same place for different blocks.

This is how I want it to display

x - TSB  | x - NoAgent
  x - OSA  | x - LO
  x - IP   | x - UEE
  x - MES  | x - SIT
  x - NoVM | x - RNA
  x - NSR  | x - ITF
  x - OTH

If the value is 0 then I leave the info blank if both are blank then I want to leave the whole line out.

This is how it however displays

9 - MES  |   
3 - NoVM |  
7 - IP   |  
         | 5 - LO 
6 - OTH  |  
         | 6 - RNA 
         | 4 - SIT 
3 -  TSB |

Is there a way to created first all variables before creating the output? I tried that but then I end up in the problem that the variable is out-of-scope.

Looking forward to suggestions

The XML looks like this:

 <?xml version="1.0" encoding="utf-8"?>
 <DialStats>
    <Countries Country="France">
     <Products Product="Office">
       <Dispositions Result="Agent Voicemail / Message" Count="11" />
       <Dispositions Result="Did Not Leave Voicemail" Count="37" />
       <Dispositions Result="Information Provided" Count="13" />
       <Dispositions Result="Lost Opportunity" Count="1" />
       <Dispositions Result="No Agent Available" Count="1" />
       <Dispositions Result="Ring No Answer" Count="6" />
       <Dispositions Result="SIT Tone" Count="3" />
       <Dispositions Result="Tour / Sale / Booking" Count="7" />
     </Products>
   </Countries>
   <Countries Country="Italy">
     <Products Product="Office">
       <Dispositions Result="Did Not Leave Voicemail" Count="1" />
       <Dispositions Result="Information Provided" Count="6" />
       <Dispositions Result="Non-Sales Related" Count="1" />
       <Dispositions Result="Other" Count="6" />
       <Dispositions Result="Ring No Answer" Count="7" />
       <Dispositions Result="SIT Tone" Count="5" />
       <Dispositions Result="Updated Existing Enquiry" Count="13" />
     </Products>
   </Countries>
   <Countries Country="Netherlands">
     <Products Product="Office">
       <Dispositions Result="Agent Voicemail / Message" Count="1" />
       <Dispositions Result="Information Provided" Count="17" />
       <Dispositions Result="Ring No Answer" Count="3" />
       <Dispositions Result="Tour / Sale / Booking" Count="2" />
     </Products>
  </Countries>
 </DialStats>

Many different Countries possible.

Thanks 输出量

(edited)

I would suggest you try a different approach. The following stylesheet:

XSLT 1.0

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

<xsl:variable name="categories">
    <category row="1">Agent Voicemail / Message</category>
    <category row="1">Did Not Leave Voicemail</category>
    <category row="1">Information Provided</category>
    <category row="1">Lost Opportunity</category>
    <category row="1">No Agent Available</category>
    <category row="1">Ring No Answer</category>
    <category row="2">SIT Tone</category>
    <category row="2">Tour / Sale / Booking</category>
    <category row="2">Non-Sales Related</category>
    <category row="2">Other</category>
    <category row="2">Updated Existing Enquiry</category>
</xsl:variable>

<xsl:variable name="col-set" select="exsl:node-set($categories)/category" />

<xsl:template match="/">
    <xsl:for-each select="DialStats/Countries">
        <xsl:variable name="country" select="." />
        <table border="1" style="width:30%; display:inline-block">
            <tr>
                <th colspan="{count($col-set[@row='1'])}">
                    <xsl:value-of select="$country/@Country"/>
                </th>
            </tr>
            <tr>
                <xsl:for-each select="$col-set[@row='1']">
                    <th><xsl:value-of select="."/></th>
                </xsl:for-each>
            </tr>
            <tr>
                <xsl:for-each select="$col-set[@row='1']">
                    <td>
                        <xsl:value-of select="$country/Products/Dispositions[@Result=current()]/@Count"/>
                    </td>
                </xsl:for-each>
            </tr>
            <tr>
                <xsl:for-each select="$col-set[@row='2']">
                    <th><xsl:value-of select="."/></th>
                </xsl:for-each>
            </tr>
            <tr>
                <xsl:for-each select="$col-set[@row='2']">
                    <td>
                        <xsl:value-of select="$country/Products/Dispositions[@Result=current()]/@Count"/>
                    </td>
                </xsl:for-each>
            </tr>
        </table>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

when applied to your input example, will produce:

<?xml version="1.0" encoding="UTF-8"?>
<table border="1" style="width:30%; display:inline-block">
   <tr>
      <th colspan="6">France</th>
   </tr>
   <tr>
      <th>Agent Voicemail / Message</th>
      <th>Did Not Leave Voicemail</th>
      <th>Information Provided</th>
      <th>Lost Opportunity</th>
      <th>No Agent Available</th>
      <th>Ring No Answer</th>
   </tr>
   <tr>
      <td>11</td>
      <td>37</td>
      <td>13</td>
      <td>1</td>
      <td>1</td>
      <td>6</td>
   </tr>
   <tr>
      <th>SIT Tone</th>
      <th>Tour / Sale / Booking</th>
      <th>Non-Sales Related</th>
      <th>Other</th>
      <th>Updated Existing Enquiry</th>
   </tr>
   <tr>
      <td>3</td>
      <td>7</td>
      <td/>
      <td/>
      <td/>
   </tr>
</table>
<table border="1" style="width:30%; display:inline-block">
   <tr>
      <th colspan="6">Italy</th>
   </tr>
   <tr>
      <th>Agent Voicemail / Message</th>
      <th>Did Not Leave Voicemail</th>
      <th>Information Provided</th>
      <th>Lost Opportunity</th>
      <th>No Agent Available</th>
      <th>Ring No Answer</th>
   </tr>
   <tr>
      <td/>
      <td>1</td>
      <td>6</td>
      <td/>
      <td/>
      <td>7</td>
   </tr>
   <tr>
      <th>SIT Tone</th>
      <th>Tour / Sale / Booking</th>
      <th>Non-Sales Related</th>
      <th>Other</th>
      <th>Updated Existing Enquiry</th>
   </tr>
   <tr>
      <td>5</td>
      <td/>
      <td>1</td>
      <td>6</td>
      <td>13</td>
   </tr>
</table>
<table border="1" style="width:30%; display:inline-block">
   <tr>
      <th colspan="6">Netherlands</th>
   </tr>
   <tr>
      <th>Agent Voicemail / Message</th>
      <th>Did Not Leave Voicemail</th>
      <th>Information Provided</th>
      <th>Lost Opportunity</th>
      <th>No Agent Available</th>
      <th>Ring No Answer</th>
   </tr>
   <tr>
      <td>1</td>
      <td/>
      <td>17</td>
      <td/>
      <td/>
      <td>3</td>
   </tr>
   <tr>
      <th>SIT Tone</th>
      <th>Tour / Sale / Booking</th>
      <th>Non-Sales Related</th>
      <th>Other</th>
      <th>Updated Existing Enquiry</th>
   </tr>
   <tr>
      <td/>
      <td>2</td>
      <td/>
      <td/>
      <td/>
   </tr>
</table>

rendered as:

在此处输入图片说明

The table's structure is constant and does not depend on the incoming data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM