title: Perl XML to tab delimited text file with XSLT (or not)
body: <p>Novice Perl programmer, trying to convert simple xml string to a <strong>tab delimited text file</strong>.
  I struggled with using XML::Parser (and XML::Twig/Simple and even XSLT), but I couldn't figure out how to get the main data parts to be the column headings. </p>
  
  <p>Then I started trying to do it with XSLT, but I can't figure out how to get a separator between the elements -- (then I would just use split and/or join?) but they all just run together in one string.</p>
  
  <p>I just manually printed the column headings manually. Is there an easy way to do that with the template?</p>
  
  <p>Similar questions I looked at, but couldn't see any separators being added to my files. <a href="https://stackoverflow.com/questions/13291694/xml-to-tab-delimited-text">XML to Tab delimited Text</a>
  <a href="https://stackoverflow.com/questions/4912900/modifying-a-xslt-for-converting-xml-to-tab-delimited-text-file">Modifying a XSLT for converting XML to tab delimited text file</a></p>
  
  <p>Questions:</p>
  
  <ol>
  <li><p>What's the easiest way to do this, generally, and should I be even using XSLT (which I've been trying to understand). </p></li>
  <li><p>How can I fix the below to do this?</p></li>
  </ol>
  
  <p>It seems like I'm close but only need to get a delimiter into the XSLT output string so I can split it and then join it with "\t" in my output to tab-delimited text file. ??</p>
  
  <p>This is my XML (SMS logs from Twilio):</p>
  
  <pre><code>  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
    &lt;TwilioResponse&gt;
       &lt;SMSMessages end="49" firstpageuri="/2010-04-01/Accounts/ACcbaa0/SMS/Messages?Page=0&amp;amp;PageSize=50" lastpageuri="/2010-04-01/Accounts/ACcbaa/SMS/Messages?Page=54&amp;amp;PageSize=50" nextpageuri="/2010-04-01/Accounts/ACcbaa0103c/SMS/Messages?Page=1&amp;amp;PageSize=50&amp;amp;AfterSid=SMc20cf7" numpages="55" page="0" pagesize="50" previouspageuri="" start="0" total="2703" uri="/2010-04-01/Accounts/ACcbaa0103cf/SMS/Messages"&gt;
          &lt;SMSMessage&gt;
             &lt;Sid&gt;SMe24eb108b7eb6a3b&lt;/Sid&gt;
             &lt;DateCreated&gt;Fri, 09 Aug 2013 00:07:59 +0000&lt;/DateCreated&gt;
             &lt;DateUpdated&gt;Fri, 09 Aug 2013 00:07:59 +0000&lt;/DateUpdated&gt;
             &lt;DateSent&gt;Fri, 09 Aug 2013 00:07:59 +0000&lt;/DateSent&gt;
             &lt;AccountSid&gt;ACcbaa0103c4141e5cd754042cb424d4ff&lt;/AccountSid&gt;
             &lt;To&gt;+14444444444&lt;/To&gt;
             &lt;From&gt;+15555555555&lt;/From&gt;
             &lt;Body&gt;Hi there!&lt;/Body&gt;
             &lt;Status&gt;sent&lt;/Status&gt;
             &lt;Direction&gt;outbound-api&lt;/Direction&gt;
             &lt;Price&gt;-0.01000&lt;/Price&gt;
             &lt;PriceUnit&gt;USD&lt;/PriceUnit&gt;
             &lt;ApiVersion&gt;2010-04-01&lt;/ApiVersion&gt;
             &lt;Uri&gt;/2010-04-01/Accounts/ACcbaa01/SMS/Messages/SMe24eb108b&lt;/Uri&gt;
          &lt;/SMSMessage&gt;
          &lt;SMSMessage&gt;
              ... etc. ...
          &lt;/SMSMessage&gt;
       &lt;/SMSMessages&gt;
    &lt;/TwilioResponse&gt;
  </code></pre>
  
  <p>This is the XSLT I was trying to use:</p>
  
  <pre><code>   &lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
     &lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"&gt;
     &lt;xsl:template match="//TwilioResponse"&gt;
     &lt;xsl:for-each select="SMSMessage"&gt;
         &lt;xsl:value-of select="Sid"/&gt;
         &lt;!-- I tried all these, too: &amp;#x20   &amp;#x9;  even &amp;#xA;   --&gt;
         &lt;xsl:text&gt;&amp;#09;&lt;/xsl:text&gt;
         &lt;!-- I also tried this from another SO question --&gt;
         &lt;xsl:if test="position() != last()"&gt;, &lt;/xsl:if&gt;
         &lt;xsl:value-of select="DateCreated"/&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="DateUpdated"/&gt;
         &lt;xsl:text&gt;&amp;#09;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="DateSent"/&gt;
         &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="AccountSid"/&gt;
         &lt;xsl:text&gt;&amp;#09;&lt;/xsl:text&gt;
         &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;
         &lt;xsl:text&gt;&amp;#x20;&lt;/xsl:text&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="To"/&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="From"/&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="Body"/&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="Status"/&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="Direction"/&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="Price"/&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="PriceUnit"/&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="ApiVersion"/&gt;
         &lt;xsl:text&gt;&amp;#x9;&lt;/xsl:text&gt;
         &lt;xsl:value-of select="Uri"/&gt;
         &lt;!-- I tried both of these: line feed char --&gt;
         &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;
         &lt;xsl:text&gt;&amp;#10;&lt;/xsl:text&gt;
       &lt;/xsl:for-each&gt;
     &lt;/xsl:template&gt;
   &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p>And this is the relevant part of my Perl code:</p>
  
  <pre><code>use XML::XSLT;
  
  my $logs = $twilio -&gt; GET ('SMS/Messages');
  my $string = $logs-&gt;{content};
  
  my $xsl = 'xsl.txt';
  my $xslt = XML::XSLT-&gt;new ($xsl);
  $xslt-&gt;transform ($string);
  my $xsltToString = $xslt-&gt;toString;
  
      print $xsltToString;
  
  my $columnHeadings = "Sid\tDateCreated\tDateUpdated\tDateSent\tAccountSid\tTo\tFrom\tBody\tStatus\tDirection\tPrice\tPriceUnit\tApiVersion\tUri\n";
  
  open(my $fh, '&gt;', 'textfile.txt') || die("Unable to open file. $!");
      print $fh  $columnHeadings;
      foreach my $k (@split) {
          print $fh join("\t", $xsltToString) . "\t";
      }       
          #print $fh split("\t", $val). "\t"; ;
  close($fh);
  $xslt-&gt;dispose();
  
  
  # P.S. I'm sure there's a better way to check and see how many lines were saved.
  
  my $xmllines = 0;
  open $fh, '&lt;', 'textfile.txt' or die "Could not open file. $!";
     while (&lt;$fh&gt;) {
        $xmllines++;
     }
  print ("\n" . $xmllines . " lines saved to tab-delimited logs textfile. \n");   
  close $fh;  
  </code></pre>
  
  <p>My output is all one thing with no separation between any of the elements. </p>