xsl-list
[Top] [All Lists]

Re: Converting a Batch File to XML

2004-07-26 06:33:24
Hi Garvin,

I have a flat file that I need to convert to an XML structure. Now I
can do this if the records in the file had the same structure, this
is fairly simple. But my source fixed length file has mutliple
records that need to be associated to a single node on the target
xml. For example, my file is structured as follows...

As you're doing this with XSLT 1.0, then you may as well parse the
string directly rather than going through an intermediate XML form
(since doing the grouping on the XML will need the same kind of code
as parsing the string, and the string will be a lot less
memory-intensive than the XML).

Assuming that you have some way of getting your string into the
stylesheet (through a parameter), you need recursive templates that
work through the string using substring-before() and substring-after()
functions. Something like:

<xsl:template name="parse-data">
  <xsl:param name="string" />
  <xsl:if test="$string">
    <someRoot>
      <header>
        <headerTag>
          <xsl:value-of select="substring-after(
                                  substring-before($string,
                                                   '&#xA;'),
                                  'H-')" />
        </headerTag>
      </header>
      <xsl:call-template name="parse-orders">
        <xsl:with-param name="string"
          select="substring-after($string, '&#xA;')" />
      </xsl:call-template>
    </someRoot>
  </xsl:if>
</xsl:template>

<xsl:template name="parse-orders">
  <xsl:param name="string" />
  <xsl:if test="$string">
    <record>
      <order>
        <xsl:call-template name="parse-items">
          <xsl:with-param name="string"
            select="substring-before($string, 'S-')" />
        </xsl:call-template>
        <summary>
          <summaryTag>
            <xsl:variable name="summary"
              select="substring-after($string, 'S-')" />
            <xsl:choose>
              <xsl:when test="contains($summary, '&#xA;')">
                <xsl:value-of select="substring-before($summary, '&#xA;')" />
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="$summary" />
              </xsl:otherwise>
            </xsl:choose>
          </summaryTag>
        </summary>
      </order>
    </record>
    <xsl:call-template name="parse-orders">
      <xsl:with-param name="string"
        select="substring-after(substring-after($string, '&#xA;S-'),
                                '&#xA;')" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

<xsl:template name="parse-items">
  <xsl:param name="string" />
  <xsl:if test="$string">
    <item>
      <itemTag>
        <xsl:variable name="item"
          select="substring-after($string, 'I-')" />
        <xsl:choose>
          <xsl:when test="contains($item, '&#xA;')">
            <xsl:value-of select="substring-before($item, '&#xA;')" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$item" />
          </xsl:otherwise>
        </xsl:choose>
      </itemTag>
    </item>
    <xsl:call-template name="parse-items">
      <xsl:with-param name="string"
        select="substring-after($string, '&#xA;')" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

Call the parse-data template as in:

  <xsl:call-template name="parse-data">
    <xsl:with-param name="string" select="..." />
  </xsl:call-template>

I hope that gets you part way there...
  
Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/