title: XML to Fixed width text file formatted details
body: <p>I have an XML like this</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;Report&gt;
    &lt;table1&gt;
      &lt;Detail_Collection&gt;
        &lt;Detail&gt;
          &lt;ReceiptNo&gt;RN12345678&lt;/ReceiptNo&gt;
          &lt;ReceiptDate&gt;1980/11/11&lt;/ReceiptDate&gt;
          &lt;LastName&gt;Dela Cruz&lt;/LastName&gt;
          &lt;FirstName&gt;Juan&lt;/FirstName&gt;
          &lt;PurchaseDetails&gt;
            &lt;Item&gt;Wood&lt;/Item&gt;
            &lt;Price&gt;25.65&lt;/Price&gt;
            &lt;Quantity&gt;2&lt;/Quantity&gt;
          &lt;/PurchaseDetails&gt;
          &lt;PurchaseDetails&gt;
            &lt;Item&gt;Axe&lt;/Item&gt;
            &lt;Price&gt;50.56&lt;/Price&gt;
            &lt;Quantity&gt;5&lt;/Quantity&gt;
          &lt;/PurchaseDetails&gt;
        &lt;/Detail&gt;
      &lt;/Detail_Collection&gt;
    &lt;/table1&gt;
  &lt;/Report&gt;
  </code></pre>
  
  <p>and I need to convert it to a flat text file using XSLT 1.0</p>
  
  <p>I found this nice solution</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" &gt;
      &lt;xsl:output method="text" indent="no"/&gt;
  
      &lt;xsl:variable name="some_spaces" select="'                                                                  '" /&gt;
  
      &lt;xsl:template match="/"&gt;
          &lt;xsl:apply-templates select="//Detail_Collection/Detail" /&gt;
      &lt;/xsl:template&gt;
  
      &lt;xsl:template match="Detail_Collection/Detail"&gt;
          &lt;xsl:apply-templates mode="format" select="SSN"&gt;
              &lt;xsl:with-param name="width" select="number(9-1)"/&gt;
          &lt;/xsl:apply-templates&gt;
          &lt;xsl:apply-templates mode="format_date" select="DOB"&gt;
              &lt;xsl:with-param name="width" select="number(17-10)"/&gt;
          &lt;/xsl:apply-templates&gt;
          &lt;xsl:apply-templates mode="format" select="LastName"&gt;
              &lt;xsl:with-param name="width" select="number(33-18)"/&gt;
          &lt;/xsl:apply-templates&gt;
          &lt;xsl:apply-templates mode="format" select="FirstName"&gt;
              &lt;xsl:with-param name="width" select="number(46-34)"/&gt;
          &lt;/xsl:apply-templates&gt;
          &lt;xsl:apply-templates mode="format_date" select="Date"&gt;
              &lt;xsl:with-param name="width" select="number(54-47)"/&gt;
          &lt;/xsl:apply-templates&gt;
          &lt;xsl:apply-templates mode="format" select="Time"&gt;
              &lt;xsl:with-param name="width" select="number(62-55)"/&gt;
          &lt;/xsl:apply-templates&gt;
          &lt;xsl:apply-templates mode="format" select="CurrentStreetAddress1"&gt;
              &lt;xsl:with-param name="width" select="number(90-63)"/&gt;
          &lt;/xsl:apply-templates&gt;
          &lt;xsl:apply-templates mode="format" select="CurrentCity"&gt;
              &lt;xsl:with-param name="width" select="number(115-91)"/&gt;
          &lt;/xsl:apply-templates&gt;
          &lt;xsl:apply-templates mode="format" select="CurrentState"&gt;
              &lt;xsl:with-param name="width" select="number(131-116)"/&gt;
          &lt;/xsl:apply-templates&gt;
          &lt;xsl:text&gt;&amp;#10;&lt;/xsl:text&gt;
      &lt;/xsl:template&gt;
  
      &lt;xsl:template  match="node()" mode ="format"&gt;
          &lt;xsl:param name="width" /&gt;
          &lt;xsl:value-of select="substring(concat(text(),$some_spaces ), 1, $width+1)"/&gt;
      &lt;/xsl:template&gt;
      &lt;xsl:template  match="node()" mode="format_date"&gt;
          &lt;xsl:param name="width" /&gt;
          &lt;xsl:value-of select="substring(concat(translate(text(),'/',''),$some_spaces ), 1, $width+1)"/&gt;
      &lt;/xsl:template&gt;
  
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p>But the problem is that I have to format every detail according to its data type like below</p>
  
  <blockquote>
    <p><strong>Alphanumeric</strong> - should be 30 characters right filled with spaces</p>
    
    <p><strong>Numeric (Unsigned)</strong> - should be 15 characters left filled with zeroes
    e.g. 000000000012345</p>
    
    <p><strong>Numeric (signed)</strong> - should be 15 characters left filled with zeroes and
    if negative should denote    'N' e.g. N00000000012345</p>
  </blockquote>
  
  <p>From my XML file  the output should be:</p>
  
  <pre><code>RN12345678                   19801111Dela Cruz                    Juan               Wood               000000000002565000000000000002
  RN12345678                   19801111Dela Cruz                    Juan               Axe                000000000005056000000000000005
  </code></pre>
  
  <p>and for example the prices are negative then </p>
  
  <pre><code>RN12345678                   19801111Dela Cruz                    Juan               Wood               N00000000002565000000000000002
  RN12345678                   19801111Dela Cruz                    Juan               Axe                N00000000005056000000000000005
  </code></pre>
  
  <p>and by the way i have some fields that have 300 characters (like a filler) so i dont know if I need to put 300+ spaces in the variable some_spaces</p>
  
  <p>Dates should be 8 characters YYYYMMDD.</p>
  
  <p>I have a template which im using but not sure how to put the 'N' for the negative ones and how to format the dates according to the requirement.</p>
  
  <p>Here is the template:</p>
  
  <pre><code>&lt;xsl:template name="prepend-pad"&gt;
      &lt;!-- recursive template to right justify and prepend the value with whatever padChar is passed in   --&gt;
      &lt;xsl:param name="padChar" /&gt;
      &lt;xsl:param name="padVar" /&gt;
      &lt;xsl:param name="length" /&gt;
      &lt;xsl:choose&gt;
        &lt;xsl:when test="string-length($padVar) &amp;lt; $length"&gt;
          &lt;xsl:call-template name="prepend-pad"&gt;
            &lt;xsl:with-param name="padChar" select="$padChar"/&gt;
            &lt;xsl:with-param name="padVar" select="concat($padChar,$padVar)"/&gt;
            &lt;xsl:with-param name="length" select="$length"/&gt;
          &lt;/xsl:call-template&gt;
        &lt;/xsl:when&gt;
        &lt;xsl:otherwise&gt;
          &lt;xsl:value-of select="substring($padVar,string-length($padVar) - $length + 1)" /&gt;
        &lt;/xsl:otherwise&gt;
      &lt;/xsl:choose&gt;
    &lt;/xsl:template&gt;
  </code></pre>
  
  <p>Thanks</p>