<section>
  <title>Flat File to XML</title>
  <section>
    <title>Delimited Fields, Single Record Type</title>
    <section>
      <title>Converting a CSV File to XML Using Default Record Mapping (countries-default)</title>
      <titleabbrev>countries-default</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>CSV</secondary>
      </indexterm>
      <indexterm>
        <primary>record mapping</primary>
        <secondary>default</secondary>
      </indexterm>
      <indexterm>
        <primary>field delimiter</primary>
        <secondary>comma</secondary>
      </indexterm>
      <para>This example shows a simple resources script that will map a CSV file to XML using default record mapping.
      </para>
      <para>
The input file is a CSV file.
      </para>
      <figure id="countires.csv" xreflabel="countries.csv flat file">
        <title>Input flat file countries.csv</title>
        <programlisting>
          <![CDATA[
code,name
#ABW,ARUBA
ATF,"FRENCH SOUTHERN TERRITORIES, D.R. OF"
VUT,VANUATU
WLF,WALLIS & FUTUNA ISLANDS
]]>
        </programlisting>
      </figure>
      <para>
This file has a number of properties.
        <itemizedlist>
          <listitem>
            <para>The first row is a header with comma-separated column
            labels.</para>
          </listitem>
          <listitem>
            <para>The second row is commented out.</para>
          </listitem>
          <listitem>
            <para>The third row has a field value, enclosed in quotes, that
contains an embedded comma.
            </para>
          </listitem>
          <listitem>
            <para>The fifth row has a field value that contains a '<![CDATA[&]]>'
symbol, which is a special character in XML, and must therefore be escaped in
XML output as the entity '<![CDATA[&amp;]]>'.
            </para>
          </listitem>
        </itemizedlist>
      </para>
      <para>Shown below is the simplest possible resources script that will read
    this data and output it as XML.
      </para>
      <programlisting>
        <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="countries">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="countries-doc"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="countries-doc" name="countries">
    <sx:flatFileReader>
      <sx:commentStarter value="#"/>
      <sx:fieldDelimiter value=","/>
      <sx:urlSource url="data/countries.csv"/>
    </sx:flatFileReader>
  </sx:recordContent>

</sx:resources>
]]>
      </programlisting>
      <para>This resources script produces the following output.
      </para>
      <programlisting>
        <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<countries>
  <record>
    <code>ATF</code>
    <name>FRENCH SOUTHERN TERRITORIES, D.R. OF</name>
  </record>
  <record>
    <code>VUT</code>
    <name>VANUATU</name>
  </record>
  <record>
    <code>WLF</code>
    <name>WALLIS &amp; FUTUNA ISLANDS</name>
  </record>
</countries>
]]>
      </programlisting>
      <para>Note the following properties of the XML output.
      </para>
      <itemizedlist>
        <listitem>
          <para>The root element name comes from the
            <link xlink:href="../guide/index.html#sx:recordContent">sx:recordContent</link>
                element's
            <sgmltag class="attribute">name</sgmltag>
attribute, if it has one, and if not
  it defaults to
            <sgmltag>document</sgmltag>
.
          </para>
        </listitem>
        <listitem>
          <para>The record element name defaults to
            <sgmltag>record</sgmltag>
.
          </para>
        </listitem>
        <listitem>
          <para>Each field is mapped to an element, and the name of the
              element defaults to the column label.
          </para>
        </listitem>
      </itemizedlist>
    </section>
    <section>
      <title>Converting a CSV File to XML Using Custom Record Mapping (countries-custom)</title>
      <titleabbrev>countries-custom</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>CSV</secondary>
      </indexterm>
      <para>
An
        <link xlink:href="../guide/index.html#sx:recordMapping">sx:recordMapping</link>
element positioned inside an
        <link xlink:href="../guide/index.html#sx:recordContent">sx:recordContent</link>
element allows for custom record mapping to XML.  This is optional, since there is a default mapping that emits
the canonical XML representation of records.  But typically the XML you want
is different from the canonical representation, you may want a field mapped to an attribute rather
than an element, for example, or perhaps some additional literal elements around the field mappings.
      </para>
      <para>
Continuing with the previous example, suppose you want the following output.
      </para>
      <programlisting>
        <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<countries>
  <country countryCode="ATF">
    <countryName>FRENCH SOUTHERN TERRITORIES, D.R. OF</countryName>
  </country>
  <country countryCode="VUT">
    <countryName>VANUATU</countryName>
  </country>
  <country countryCode="WLF">
    <countryName>WALLIS &amp; FUTUNA ISLANDS</countryName>
  </country>
</countries>
]]>
      </programlisting>
      <para>
The following resources script does the job.
      </para>
      <programlisting>
        <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">
   
  <sx:service id="countries">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="countries"/> 
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="countries">
    <sx:flatFileReader>
      <sx:urlSource url="data/countries.csv"/>
      <sx:flatFile ref="countriesFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="countriesToXmlMapping"/>
  </sx:recordContent>
  
  <sx:flatFile id="countriesFile">
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordType name="country">
        <sx:fieldDelimiter value=","/>
        <sx:delimitedField name="code"/>
        <sx:delimitedField name="name"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>      
  
  <sx:recordMapping id="countriesToXmlMapping">
    <countries>
      <sx:onRecord>
        <country>
          <sx:fieldElementMap field="name" element="countryName"/>  
          <sx:fieldAttributeMap field="code" attribute="countryCode"/>
        </country>  
      </sx:onRecord>
    </countries>
  </sx:recordMapping>  
  
</sx:resources>
]]>
      </programlisting>
      <para>
You can also take the default mappings for some fields and map others explicitly.  For example,
      </para>
      <programlisting>
        <![CDATA[
<sx:recordMapping id="countries2xml">
  <countries>
    <sx:onRecord>
      <country>
        <sx:defaultFieldElementMap fields="*" except="code"/>
        <sx:fieldAttributeMap field="code" attribute="countryCode"/>
      </country>
    </sx:onRecord>
  </countries>
</sx:recordMapping>
]]>
      </programlisting>
      <para>
Here, the
        <link xlink:href="../guide/index.html#sx:defaultFieldElementMap">sx:defaultFieldElementMap</link>
element maps all the fields in the record
to elements with the same names, except the field name "code". This field is handled
separately, with the
        <link xlink:href="../guide/index.html#sx:fieldAttributeMap">sx:fieldAttributeMap</link>
element.
      </para>
    </section>

    <section>
      <title>Converting a CSV file to XML with Record Validation (countries-validated)</title>
      <titleabbrev>countries-validated</titleabbrev>
      <indexterm>
        <primary>record filter</primary>
        <secondary>schema validation</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>CSV</secondary>
      </indexterm>
      <para>
The example below shows how to convert a flat file to XML. Each row in the flat 
file is validated with Sun's multi schema validator (MSV), and if an error is
encountered, the row is discarded, but processing continues.  In addition, the
output XML is also validated with Sun's MSV, and if that should fail, processing is stopped.
      </para>
      <para>
This time the input file has an invalid country code in the first record.
      </para>
      <programlisting>
        <![CDATA[
code,name
ATFX,"FRENCH SOUTHERN TERRITORIES, D.R. OF"
VUT,VANUATU
WLF,WALLIS & FUTUNA ISLANDS
]]>
      </programlisting>
      <para>
The desired output is
      </para>
      <programlisting>
        <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<countries>
  <country countryCode="ATF">
    <countryName>FRENCH SOUTHERN TERRITORIES, D.R. OF</countryName>
  </country>
  <country countryCode="VUT">
    <countryName>VANUATU</countryName>
  </country>
  <country countryCode="WLF">
    <countryName>WALLIS &amp; FUTUNA ISLANDS</countryName>
  </country>
</countries>
]]>
      </programlisting>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-countries.xml">
        <title>Resources script resources-countries.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:msv="http://www.servingxml.com/extensions/msv">

  <sx:service id="countries">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="countries"/>
        <msv:schemaValidator>
          <sx:urlSource url="data/countries.xsd"/>
        </msv:schemaValidator>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:flatFile id="countriesFile">
    <sx:commentStarter value="#"/>
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordType ref="country"/>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:flatRecordType id="country" name="country">
    <sx:fieldDelimiter value=","/>
    <sx:delimitedField name="code"/>
    <sx:delimitedField name="name"/>
  </sx:flatRecordType>

  <sx:flatFile id="discardFile">
    <sx:flatFileBody>
      <sx:flatRecordType name="countryDiscard">
        <sx:fieldDelimiter value=","/>
        <sx:delimitedField name="message"/>
        <sx:flatRecordType ref="country"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="countriesToXmlMapping">
    <countries>
      <sx:onRecord>
        <country>
          <sx:fieldElementMap field="name" element="countryName"/>
          <sx:fieldAttributeMap field="code" attribute="countryCode"/>
        </country>
      </sx:onRecord>
    </countries>
  </sx:recordMapping>

  <sx:recordContent id="countries">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:urlSource url="data/countriesWithDiscards.csv"/>
        <sx:flatFile ref="countriesFile"/>
      </sx:flatFileReader>
      <msv:recordValidator>
        <sx:urlSource url="data/country-record.xsd"/>
      </msv:recordValidator>
      <sx:discardHandler>
        <sx:log message="{$sx:message}"/>
        <sx:modifyRecord>
          <sx:newField name="message" value="{$sx:message}"/>
        </sx:modifyRecord>
        <sx:flatFileWriter>
          <sx:fileSink file="output/countryDiscards.csv"/>
          <sx:flatFile ref="discardFile"/>
        </sx:flatFileWriter>
      </sx:discardHandler>
    </sx:recordStream>
    <sx:recordMapping ref="countriesToXmlMapping"/>
  </sx:recordContent>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>The schema to validate an individual country record is shown below.
      </para>
      <figure id="country-record.xsd">
        <title>XML Schema file country-record.xsd</title>
        <programlisting>
          <![CDATA[
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

 <!-- This element's name matches the value of the name attribute in the sx:flatRecordType element. -->
 <xs:element name="country" type="CountryType"/>

 <xs:complexType name="CountryType">
  <xs:sequence>
   <xs:element name="code" type="CountryCode"/>
   <xs:element name="name" type="xs:string"/>
  </xs:sequence>
 </xs:complexType>

  <xs:simpleType name='CountryCode'>
    <xs:restriction base='xs:string'>
      <xs:length value='3' fixed='true'/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>
]]>
        </programlisting>
      </figure>
      <para>
You run this example on the command line by entering
      </para>
      <programlisting>
        <![CDATA[
servingxml -r resources-countries.xml -o output/countries.xml countries
]]>
      </programlisting>
      <para>The following error message will be written to the log:
      </para>
      <programlisting>
        <![CDATA[
Error in record "country" on line 1.  the length of the value is 4, but the required length is 3.
]]>
      </programlisting>
      <para>The remaining two rows will be written to the output file.
      </para>
    </section>
    <section>
      <title>Converting flat files with fields that end either with a delimiter or a maximum width (field has max width)</title>
      <titleabbrev>field has max width</titleabbrev>
      <indexterm>
        <primary>delimited field</primary>
        <secondary>max width</secondary>
      </indexterm>
      <para>
The example below shows how to convert a flat file with start/end record 
delimiters to XML.
      </para>
      <para>
The input file is shown below.
      </para>
      <programlisting>
        <![CDATA[
1231234
1 123
12 12
]]>
      </programlisting>
      <para>
This file has the following structure.
      </para>
      <itemizedlist>
        <listitem>
          <para>The first record consists of a field of length 3 ("123") followed by a field of length 4 ("1234")
          </para>
        </listitem>
        <listitem>
          <para>The second line consists of a field of length 1 ("1") followed by a field of length 3 ("123")
          </para>
        </listitem>
      </itemizedlist>
      <para>Each field has a maximum width, but the field may be terminated by a delimiter (here whitespace) before it attains that width.
      </para>
      <para>
The desired output is shown below.
      </para>
      <programlisting>
        <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<document>
  <record>
    <field1>123</field1>
    <field2>1234</field2>
  </record>
  <record>
    <field1>1</field1>
    <field2>123</field2>
  </record>
  <record>
    <field1>12</field1>
    <field2>12</field2>
  </record>
</document>
]]>
      </programlisting>
      <para>
The following resources script does the transformation.
      </para>
      <programlisting>
        <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="fieldHasMaxWidth">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="fieldHasMaxWidthDoc"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="fieldHasMaxWidthDoc" name="document">
    <sx:flatFileReader>
      <sx:urlSource url="data/fieldHasMaxWidth.txt"/>
      <sx:flatFile ref="fieldHasMaxWidthFile"/>
    </sx:flatFileReader>
  </sx:recordContent>

  <sx:flatFile id="fieldHasMaxWidthFile">
    <sx:flatFileBody>
      <sx:flatRecordType name="record">
        <sx:fieldDelimiter>
          <sx:whitespaceSeparator/>
        </sx:fieldDelimiter>
        <sx:delimitedField name="field1" maxWidth="3"/>
        <sx:delimitedField name="field2" maxWidth="4"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

</sx:resources>
]]>
      </programlisting>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-fieldHasMaxWidth.xml  
  -o output/fieldHasMaxWidth.xml fieldHasMaxWidth
]]>
        </programlisting>
      </para>
    </section>
    <section id="tasks-eg" xreflabel="tasks">
      <title>Converting a flat file to XML with one level of grouping (tasks)</title>
      <titleabbrev>tasks (CSV) to XML</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>CSV</secondary>
      </indexterm>
      <indexterm>
        <primary>group</primary>
        <secondary>by</secondary>
      </indexterm>
      <para>
The example below shows how to convert a flat file to XML with grouping levels.
      </para>
      <para>
The input file is a CSV file.
      </para>
      <figure id="tasks.csv">
        <title>Input flat file tasks.csv</title>
        <programlisting>
          <![CDATA[
project_id, task_name, task_start, task_finish
4001,task1,01/01/2003,01/31/2003
4001,task2,02/01/2003,02/28/2003
4001,task3,03/01/2003,03/31/2003
4002,task1,04/01/2003,04/30/2003
4002,task2,05/01/2003,05/31/2003
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="tasks.xml">
        <title>Output XML file tasks.xml</title>
        <programlisting>
          <![CDATA[
 <?xml version="1.0" encoding="utf-8" ?> 
<Projects>
  <Project projectID="4001">
    <Tasks>
      <Task name="task1" start="01/01/2003" finish="01/31/2003" /> 
      <Task name="task2" start="02/01/2003" finish="02/28/2003" /> 
      <Task name="task3" start="03/01/2003" finish="03/31/2003" /> 
    </Tasks>
  </Project>
  <Project projectID="4002">
    <Tasks>
      <Task name="task1" start="04/01/2003" finish="04/30/2003" /> 
      <Task name="task2" start="05/01/2003" finish="05/31/2003" /> 
    </Tasks>
  </Project>
</Projects>
]]></programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-tasks.xml">
        <title>Resources script resources-tasks.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="tasks">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="tasks"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="tasks">
    <sx:flatFileReader>
      <sx:urlSource url="data/tasks.csv"/>
      <sx:flatFile ref="tasksFlatFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="tasksToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="tasksFlatFile">
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordType name="task">
        <sx:fieldDelimiter value=","/>
        <sx:delimitedField name="project_id"/>
        <sx:delimitedField name="task_name"/>
        <sx:delimitedField name="task_start"/>
        <sx:delimitedField name="task_finish"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="tasksToXmlMapping">
    <Projects>
      <sx:groupBy fields="project_id">
        <Project>
          <sx:fieldAttributeMap field="project_id" attribute="projectID"/>
          <Tasks>
            <sx:onRecord>
              <Task>
                <sx:fieldAttributeMap field="task_name" attribute="name"/>
                <sx:fieldAttributeMap field="task_start" attribute="start"/>
                <sx:fieldAttributeMap field="task_finish" attribute="finish"/>
              </Task>
            </sx:onRecord>
          </Tasks>
        </Project>
      </sx:groupBy>
    </Projects>
  </sx:recordMapping>
  
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-tasks.xml -o output/tasks.xml tasks
]]>
        </programlisting>
      </para>
    </section>

    <section id="timesheets-eg"  xreflabel="timesheets">
      <title>Converting a flat file to XML with many levels of grouping (timesheets)</title>
      <titleabbrev>timesheets (CSV) to XML (grouped)</titleabbrev>
      <indexterm>
        <primary>group</primary>
        <secondary>by</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>CSV</secondary>
      </indexterm>
      <para>
The example below shows how to convert a flat file to XML with many grouping 
levels.
      </para>
      <para>
The input file is a CSV file.
      </para>
      <figure id="timesheets.csv">
        <title>Input flat file timesheets.csv</title>
        <programlisting>
          <![CDATA[
TimePeriod,Start,Finish,Resource,Task,ActualDate,Amount
1,2/9/2004,2/15/2004,Joe_100,1001,2/9/2004,8
1,2/9/2004,2/15/2004,Joe_100,1001,2/10/2004,4
1,2/9/2004,2/15/2004,Joe_100,1002,2/11/2004,8
1,2/9/2004,2/15/2004,Joe_100,1003,2/10/2004,4
1,2/9/2004,2/15/2004,Joe_100,1003,2/12/2004,8
1,2/9/2004,2/15/2004,Mark_101,1001,2/10/2004,8
1,2/9/2004,2/15/2004,Mark_101,1001,2/14/2004,8
1,2/9/2004,2/15/2004,Mark_101,1006,2/9/2004,8
1,2/9/2004,2/15/2004,Mark_101,1008,2/12/2004,4
1,2/9/2004,2/15/2004,Mark_101,1008,2/13/2004,4
2,2/16/2004,2/22/2004,Joe_100,1001,2/16/2004,8
2,2/16/2004,2/22/2004,Joe_100,1001,2/17/2004,4
2,2/16/2004,2/22/2004,Joe_100,1002,2/17/2004,4
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="timesheets.xml">
        <title>Output XML file timesheets.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<TimePeriods>
  <TimePeriod start="2/9/2004" finish="2/15/2004">
    <Timesheets>
      <Timesheet resource="Joe_100">
        <TimesheetEntries>
          <TimesheetEntry task="1001">
            <DailyActuals>
              <Actual actualDate="2/9/2004" amount="8"/>
              <Actual actualDate="2/10/2004" amount="4"/>
            </DailyActuals>
          </TimesheetEntry>
          <TimesheetEntry task="1002">
            <DailyActuals>
              <Actual actualDate="2/11/2004" amount="8"/>
            </DailyActuals>
          </TimesheetEntry>
          <TimesheetEntry task="1003">
            <DailyActuals>
              <Actual actualDate="2/10/2004" amount="4"/>
              <Actual actualDate="2/12/2004" amount="8"/>
            </DailyActuals>
          </TimesheetEntry>
        </TimesheetEntries>
      </Timesheet>
      <Timesheet resource="Mark_101">
        <TimesheetEntries>
          <TimesheetEntry task="1001">
            <DailyActuals>
              <Actual actualDate="2/10/2004" amount="8"/>
              <Actual actualDate="2/14/2004" amount="8"/>
            </DailyActuals>
          </TimesheetEntry>
          <TimesheetEntry task="1006">
            <DailyActuals>
              <Actual actualDate="2/9/2004" amount="8"/>
            </DailyActuals>
          </TimesheetEntry>
          <TimesheetEntry task="1008">
            <DailyActuals>
              <Actual actualDate="2/12/2004" amount="4"/>
              <Actual actualDate="2/13/2004" amount="4"/>
            </DailyActuals>
          </TimesheetEntry>
        </TimesheetEntries>
      </Timesheet>
    </Timesheets>
  </TimePeriod>
  <TimePeriod start="2/16/2004" finish="2/22/2004">
    <Timesheets>
      <Timesheet resource="Joe_100">
        <TimesheetEntries>
          <TimesheetEntry task="1001">
            <DailyActuals>
              <Actual actualDate="2/16/2004" amount="8"/>
              <Actual actualDate="2/17/2004" amount="4"/>
            </DailyActuals>
          </TimesheetEntry>
          <TimesheetEntry task="1002">
            <DailyActuals>
              <Actual actualDate="2/17/2004" amount="4"/>
            </DailyActuals>
          </TimesheetEntry>
        </TimesheetEntries>
      </Timesheet>
    </Timesheets>
  </TimePeriod>
</TimePeriods>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-timesheets.xml">
        <title>Resources script resources-timesheets.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">
   
  <sx:service id="timesheets"> 
    <sx:serialize>
      <sx:transform>
        <sx:content ref="timesheets"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>
  
  <sx:recordContent id="timesheets">
    <sx:flatFileReader>
      <sx:urlSource url="data/timesheets.csv"/>
      <sx:flatFile ref="timesheetsFlatFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="timesheetsToXmlMapping"/>
  </sx:recordContent>
  
  <sx:flatFile id="timesheetsFlatFile">
    <sx:commentStarter value="#"/>
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordType name="task">
        <sx:fieldDelimiter value=","/>
        <sx:delimitedField name="TimePeriod"/>
        <sx:delimitedField name="Start"/>
        <sx:delimitedField name="Finish"/>
        <sx:delimitedField name="Resource"/>
        <sx:delimitedField name="Task"/>
        <sx:delimitedField name="ActualDate"/>
        <sx:delimitedField name="Amount"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>      
  
  <sx:recordMapping id="timesheetsToXmlMapping">
    <TimePeriods>
      <sx:groupBy fields="Start">
        <TimePeriod>
          <sx:fieldAttributeMap field="Start" attribute="start"/>
          <sx:fieldAttributeMap field="Finish" attribute="finish"/>
          <Timesheets>
            <sx:groupBy fields="Start Resource">
              <Timesheet>
                <sx:fieldAttributeMap field="Resource" attribute="resource"/>
                <TimesheetEntries>
                  <sx:groupBy fields="Start Resource Task">
                    <TimesheetEntry>
                      <sx:fieldAttributeMap field="Task" attribute="task"/>
                      <DailyActuals>
                        <sx:onRecord>
                          <Actual>
                            <sx:fieldAttributeMap field="ActualDate" attribute="actualDate"/>
                            <sx:fieldAttributeMap field="Amount" attribute="amount"/>
                          </Actual>
                        </sx:onRecord>
                      </DailyActuals>
                    </TimesheetEntry>
                  </sx:groupBy>
                </TimesheetEntries>
              </Timesheet>
            </sx:groupBy>
          </Timesheets>
        </TimePeriod>
      </sx:groupBy>
    </TimePeriods>
  </sx:recordMapping>  
  
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-timesheets.xml -o output/timesheets.xml timesheets
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Converting a flat file with multi-valued fields to XML (family_data)</title>
      <titleabbrev>family_data (multi-valued) to XML</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>delimited</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>multi-valued fields</secondary>
      </indexterm>
      <indexterm>
        <primary>field delimiter</primary>
        <secondary>pipe</secondary>
      </indexterm>
      <para>
The example below shows how to convert a flat file with multi-valued fields to 
XML.
      </para>
      <para>
The input file is a pipe delimited flat file with semicolon sub-delimiters.
      </para>
      <figure id="family_data.txt">
        <title>Input flat file employees.txt</title>
        <programlisting>
          <![CDATA[
father_name|mother_name|children
Matthew|Sarah|
Scott||Damian;Janet;Paul
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="family_data.xml">
        <title>Output XML file multivalued.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<eg:families xmlns:eg="http://examples.com/">
  <eg:family>
    <eg:father-name>Matthew</eg:father-name>
    <eg:mother-name>Sarah</eg:mother-name>
    <eg:children/>
  </eg:family>
  <eg:family>
    <eg:father-name>Scott</eg:father-name>
    <eg:mother-name/>
    <eg:children>
      <eg:child>Damian</eg:child>
      <eg:child>Janet</eg:child>
      <eg:child>Paul</eg:child>
    </eg:children>
  </eg:family>
</eg:families>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-family_data.xml">
        <title>Resources script resources-multivalued.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0"?>
<sx:resources xmlns:sx="http://www.servingxml.com/core"
                    xmlns:eg="http://examples.com/">

  <sx:service id="families">                               
    <sx:serialize>
      <sx:transform>
        <sx:content ref="families"/>
        <!-- sx:removeEmptyElements elements="eg:children"/ -->
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="families">
    <sx:flatFileReader>
      <sx:flatFile ref="family-records"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="families-to-xml-mapping"/>
  </sx:recordContent>
  
  <sx:flatFile id="family-records">
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordType name="family">
        <sx:fieldDelimiter value="|"/>
        <sx:delimitedField name="father_name"/>
        <sx:delimitedField name="mother_name"/>
        <sx:delimitedField name="children">
          <sx:subfieldDelimiter value=";"/>
        </sx:delimitedField>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>
  
  <sx:recordMapping id="families-to-xml-mapping">
    <eg:families xmlns:eg="http://examples.com/">
      <sx:onRecord>
        <eg:family>
          <sx:fieldElementMap field="father_name" element="eg:father-name"/>
          <sx:fieldElementMap field="mother_name" element="eg:mother-name"/>
          <eg:children>
            <sx:fieldElementSequenceMap field="children" element="eg:child"/>
          </eg:children>
        </eg:family>
      </sx:onRecord>
    </eg:families>
  </sx:recordMapping>
  
</sx:resources>
]]>
        </programlisting>
      </figure>
      <section>
        <title>Remarks</title>
        <itemizedlist>
          <listitem>
            <para>
Note that Matthew and Sarah have no children.  If you wanted to remove the empty
              <sgmltag>myns:children</sgmltag>
element, uncomment the
              <link xlink:href="../guide/index.html#sx:removeEmptyElements">sx:removeEmptyElements</link>
element in the
              <link xlink:href="../guide/index.html#sx:transform">sx:transform</link>
block of the resources script,
            </para>
          </listitem>
        </itemizedlist>
      </section>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-family_data.xml 
    -i data/family_data.txt -o output/family_data.xml families
]]>
        </programlisting>
      </para>
    </section>
    <section id="ars-eg" xreflabel="ars">
      <title>Search and Replace with Regular Expressions in Field Mappings (ars)</title>
      <titleabbrev>ars (delimited) to XML</titleabbrev>
      <indexterm>
        <primary>date</primary>
        <secondary>today</secondary>
      </indexterm>
      <indexterm>
        <primary>group</primary>
        <secondary>by</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>delimited</secondary>
      </indexterm>
      <indexterm>
        <primary>regular expressions</primary>
        <secondary>search and replace</secondary>
      </indexterm>
      <para>
The example below shows how to convert a flat file to XML using search and 
replace with regular expressions in field mappings.
      </para>
      <para>
The input file is a carot (^) delimited flat file with a header.
      </para>
      <figure id="ars.txt">
        <title>Input flat file ars.dat</title>
        <programlisting>
          <![CDATA[
ProjectID^Project_Name^Description^PLAN_IT_RESC_DAYS^PLAN_IT_COST^ANNUAL_EBIT^ACTUAL_NPV^ACTUAL_IRR 
1234-00-0005^XOG new project insert^This is to test and verify the XOG'ing of new Project data from the ARS database.^430^59,627^100,351^3^9.2 
]]>
        </programlisting>
      </figure>
      <para>
Note the following features of this data.
        <itemizedlist>
          <listitem>
            <para>The first row is a header row.</para>
          </listitem>
          <listitem>
            <para>The fourth and fifth fields contain embedded commas in numbers, which we want to strip out.</para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="tasks.xml">
        <title>Output XML file ars.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<NikuDataBus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Header action="write" externalSource="NIKU" objectType="project" version="6.0.11"/>
  <Projects>
    <Project name="XOG new project insert" projectID="1234-00-0005" description="This is to test and verify the XOG'ing of new Project data from the ARS database.">
      <CustomInformation>
        <PLAN_IT_RESOURCE_DAYS>430</PLAN_IT_RESOURCE_DAYS>
        <PLAN_IT_COST>59627</PLAN_IT_COST>
        <ANNUAL_EBIT>100351</ANNUAL_EBIT>
        <ACTUAL_NPV>3</ACTUAL_NPV>
        <ACTUAL_IRR>9.2</ACTUAL_IRR>
      </CustomInformation>
      <General addedBy="XOG" addedDate="03/26/2005 8:10:09 PM"/>
    </Project>
  </Projects>
</NikuDataBus>
]]></programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-ars.xml">
        <title>Resources script resources-ars.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:msv="http://www.servingxml.com/extensions/msv">

  <sx:service id="ars">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="ars"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="ars">
    <sx:flatFileReader>
      <sx:flatFile ref="arsFlatFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="arsToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="arsFlatFile">
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordType name="detail">
        <sx:fieldDelimiter value="^"/>
        <sx:delimitedField name="ProjectID"/>
        <sx:delimitedField name="Project_Name"/>
        <sx:delimitedField name="Description"/>
        <sx:delimitedField name="PLAN_IT_RESC_DAYS"/>
        <sx:delimitedField name="PLAN_IT_COST"/>
        <sx:delimitedField name="ANNUAL_EBIT"/>
        <sx:delimitedField name="ACTUAL_NPV"/>
        <sx:delimitedField name="ACTUAL_IRR"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="arsToXmlMapping">
    <NikuDataBus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

      <Header version="6.0.11" action="write" objectType="project" externalSource="NIKU"/>
      <Projects>
        <sx:groupBy fields="ProjectID">
          <Project>
            <sx:fieldAttributeMap field="Project_Name" attribute="name"/>
            <sx:fieldAttributeMap field="ProjectID" attribute="projectID"/>
            <sx:fieldAttributeMap field="Description" attribute="description"/>
            <sx:onRecord>
              <CustomInformation>
                <sx:fieldElementMap field="PLAN_IT_RESC_DAYS" element="PLAN_IT_RESOURCE_DAYS"/>
                <sx:elementMap element="PLAN_IT_COST">
                  <sx:findAndReplace searchFor ="," replaceWith ="">
                    <sx:toString value="{PLAN_IT_COST}"/>
                  </sx:findAndReplace>
                </sx:elementMap>
                <sx:elementMap element="ANNUAL_EBIT">
                  <sx:findAndReplace searchFor ="," replaceWith ="">
                    <sx:toString value="{ANNUAL_EBIT}"/>
                  </sx:findAndReplace>
                </sx:elementMap>
                <sx:fieldElementMap field="ACTUAL_NPV" element="ACTUAL_NPV"/>
                <sx:fieldElementMap field="ACTUAL_IRR" element="ACTUAL_IRR"/>
              </CustomInformation>
              <General addedBy="XOG">
                <sx:fieldAttributeMap attribute="addedDate">
                  <sx:formatDateTime format="MM/dd/yyyy h:mm:ss a">
                    <sx:currentDateTime/>
                  </sx:formatDateTime>
                </sx:fieldAttributeMap>
              </General>
            </sx:onRecord>
          </Project>
        </sx:groupBy>
      </Projects>
    </NikuDataBus>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points about this script.
        <itemizedlist>
          <listitem>
            <para>
The
              <link xlink:href="../guide/index.html#sx:currentDateTime">sx:currentDateTime</link>
element evaluates to the current date with a lexical representation as defined for
              <ulink url="http://www.w3.org/TR/xmlschema-2/#dateTime">xs:dateTime</ulink>
of
              <ulink url="http://www.w3.org/TR/xmlschema-2/">XML Schema Part 2: Datatypes</ulink>
.
            </para>
          </listitem>
          <listitem>
            <para>
The
              <link xlink:href="../guide/index.html#sx:formatDateTime">sx:formatDateTime</link>
formats the XML Schema lexical representation of a date using a format string
which must must follow the syntax specified for the
              <ulink url="http://java.sun.com/j2se/1.3/docs/api/java/text/SimpleDateFormat.html">JDK SimpleDateFormat</ulink>
class..
            </para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-ars.xml -i data/ars.txt -o output/ars.xml ars 
]]>
        </programlisting>
      </para>
    </section>
    <section id="tab-delimited" xreflabel="tab-delimited">
      <title>Converting a Tab Delimited Flat File to XML (tab-delimited)</title>
      <titleabbrev>tab-delimited to XML</titleabbrev>
      <indexterm>
        <primary>field delimiter</primary>
        <secondary>tab</secondary>
      </indexterm>
      <indexterm>
        <primary>field delimiter</primary>
        <secondary>numerical entity references</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file with tab delimiters to XML.</para>
      <para>
The input file is a tab (0x09) delimited flat file with a header.
      </para>
      <figure id="tab_delimited_employees.txt">
        <title>Input flat file tab_delimited_employees.txt</title>
        <programlisting>
          <![CDATA[
employee-no	employee-name	dept	salary
00000001	Smith, Matthew	sales	150,000.00
00000002	Brown, Sarah	sales	89,000.00
00000003	Oberc, Scott	finance	110,000.00
00000004	Scott, Colette	sales	75,000.00
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="employees.xml">
        <title>Output XML file employees.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<employees>
  <employee>
    <employee-no>00000001</employee-no>
    <employee-name>Smith, Matthew</employee-name>
    <department>sales</department>
    <salary>150,000.00</salary>
  </employee>
  <employee>
    <employee-no>00000002</employee-no>
    <employee-name>Brown, Sarah</employee-name>
    <department>sales</department>
    <salary>89,000.00</salary>
  </employee>
  <employee>
    <employee-no>00000003</employee-no>
    <employee-name>Oberc, Scott</employee-name>
    <department>finance</department>
    <salary>110,000.00</salary>
  </employee>
  <employee>
    <employee-no>00000004</employee-no>
    <employee-name>Scott, Colette</employee-name>
    <department>sales</department>
    <salary>75,000.00</salary>
  </employee>
</employees>
]]></programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-tab_delimited_employees.xml">
        <title>Resources script resources-tab_delimited_employees.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="employees">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="employee-data"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="employee-data" name="employees">
    <sx:flatFileReader>
      <sx:urlSource url="data/tab_delimited_employees.txt"/>
      <sx:flatFile ref="employee-file"/>
    </sx:flatFileReader>
  </sx:recordContent>

  <sx:flatFile id="employee-file">
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:fieldDelimiter value="\t"/>
      <!-- Another way of specifying a horizontal tab character -->
      <!-- <sx:fieldDelimiter value="&#x09;"/> -->
      <sx:flatRecordType name="employee">
        <sx:delimitedField name="employee-no"/>
        <sx:delimitedField name="employee-name"/>
        <sx:delimitedField name="department"/>
        <sx:delimitedField name="salary"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points about this script.
        <itemizedlist>
          <listitem>
            <para>
The tab delimiter may be specified either with the
              <code>\t</code>
symbol, or, alternatively, with the numerical entity reference
              <![CDATA[&#x09;]]>
numerical entity
            </para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -o output/employees.xml 
    -r resources-tab_delimited_employees.xml employees 
]]>
        </programlisting>
      </para>
    </section>
  </section>
  <section>
    <title>Delimited Fields, Multiple Record Types</title>
    <section>
      <title>Converting a flat file with multiple record formats to XML with grouping (exotics)</title>
      <titleabbrev>exotics (delimited) to XML (grouped)</titleabbrev>
      <indexterm>
        <primary>group</primary>
        <secondary>by</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>delimited</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>multiple record format</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
pipe delimited flat file with multiple record formats to XM with grouping.
      </para>
      <para>
The input file is a pipe delimited file.
      </para>
      <figure id="exotics.txt">
        <title>Input flat file exotics.txt</title>
        <programlisting>
          <![CDATA[
SWAP|1234567|FLOAT|PAY|CAD|BA|2010/04/28|10000000.00
Cap|1234567||CAD|SELL|2010/04/28|0.03
SWAP|1234567|FIX|REC|CAD
Cap|1234568||CAD|SELL|2010/04/28|0.05
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="exotics.xml">
        <title>Output XML file exotics.xml</title>
        <programlisting>
          <![CDATA[
<exotics>
  <trade tradeId="1234567">
    <option>SWAP</option>
    <swapLeg style="FLOAT">
      <side>PAY</side>
      <maturityDate original="2010/04/28">2001/04/29</maturityDate>
      <currency>CAD</currency>
      <index>BA</index>
      <notional>10000000.00</notional>
    </swapLeg>
    <capSell>
      <buySell>SELL</buySell>
      <maturityDate original="2010/04/28">2001/04/28</maturityDate>
      <strike>0.03</strike>
    </capSell>
    <swapLeg style="FIX">
      <side>REC</side>
    </swapLeg>
  </trade>
  <trade tradeId="1234568">
    <option>Cap</option>
    <capBuy>
      <buySell>BUY</buySell>
      <maturityDate original="2010/04/28">2001/04/28</maturityDate>
      <strike>0.05</strike>
    </capBuy>
  </trade>
</exotics>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-exotics.xml">
        <title>Resources script resources-exotics.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0"?>

<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="exotics">
	<sx:serialize>
	  <sx:transform>
		<sx:content ref="exotics"/>
	  </sx:transform>
	</sx:serialize>
  </sx:service>

  <sx:recordContent id="exotics">
	<sx:flatFileReader>
	  <sx:fileSource file="data/exotics.txt"/>
	  <sx:flatFile ref="exoticsFlatFile"/>
	</sx:flatFileReader>
	<sx:recordMapping ref="exoticsToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="exoticsFlatFile">
	<sx:flatFileBody>
	  <sx:flatRecordTypeChoice>
		<sx:fieldDelimiter value="|"/>
		<sx:delimitedField name="recordType"/>
		<sx:delimitedField name="tradeId"/>
		<sx:delimitedField name="style"/>
		<sx:when test="recordType='Cap'">
		  <sx:flatRecordType name='Cap'>
			<sx:fieldDelimiter value="|"/>
			<sx:delimitedField name="recordType"/>
			<sx:delimitedField name="tradeId"/>
			<sx:delimitedField name="placeholder1"/>
			<sx:delimitedField name="currency"/>
			<sx:delimitedField name="buySell"/>
			<sx:delimitedField name="maturityDate"/>
			<sx:delimitedField name="strike"/>
		  </sx:flatRecordType>
		</sx:when>
		<sx:when test="recordType='SWAP' and style='FLOAT'">
		  <sx:flatRecordType name='SwapFloatingLeg'>
			<sx:fieldDelimiter value="|"/>
			<sx:delimitedField name="recordType"/>
			<sx:delimitedField name="tradeId"/>
			<sx:delimitedField name="style"/>
			<sx:delimitedField name="side"/>
			<sx:delimitedField name="currency"/>
			<sx:delimitedField name="index"/>
			<sx:delimitedField name="maturityDate"/>
			<sx:delimitedField name="notional"/>
		  </sx:flatRecordType>
		</sx:when>
		<sx:when test="recordType='SWAP' and style='FIX'">
		  <sx:flatRecordType name='SwapFixedLeg'>
			<sx:fieldDelimiter value="|"/>
			<sx:delimitedField name="recordType"/>
			<sx:delimitedField name="tradeId"/>
			<sx:delimitedField name="style"/>
			<sx:delimitedField name="side"/>
			<sx:delimitedField name="placeholder1"/>
			<sx:delimitedField name="currency"/>
		  </sx:flatRecordType>
		</sx:when>
	  </sx:flatRecordTypeChoice>
	</sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="exoticsToXmlMapping">
	<exotics>
	  <sx:groupBy fields="tradeId">
		<trade><option>
		  <sx:choose>
			<sx:when test="recordType='Cap' or (recordType='SWAP' and style='FLOAT')">
			  <sx:toString value="{recordType}"/>
			</sx:when>
		  </sx:choose></option>
		  <sx:fieldAttributeMap field="tradeId" attribute="tradeId"/>
		  <sx:onRecord recordType="Cap">
			  <sx:choose>
				<sx:when test="buySell='BUY'">
		 	<capBuy>
			  <sx:fieldElementMap field="buySell" element="buySell"/>
			  <sx:elementMap element="maturityDate">
				<sx:fieldAttributeMap field="maturityDate" attribute="original"/>
			  	<sx:choose>
			  		<sx:when test="maturityDate='2010/04/28'">
			  			<sx:toString value="2001/04/28"/>
			  		</sx:when>
			  	</sx:choose>
			  </sx:elementMap>
			  <sx:fieldElementMap field="strike" element="strike"/>
			</capBuy>
				</sx:when>
				<sx:otherwise>
		 	<capSell>
			  <sx:fieldElementMap field="buySell" element="buySell"/>
			  <sx:elementMap element="maturityDate">
				<sx:fieldAttributeMap field="maturityDate" attribute="original"/>
			  	<sx:choose>
			  		<sx:when test="maturityDate='2010/04/28'">
			  			<sx:toString value="2001/04/28"/>
			  		</sx:when>
			  	</sx:choose>
			  </sx:elementMap>
			  <sx:fieldElementMap field="strike" element="strike"/>
			</capSell>
				</sx:otherwise>
			  </sx:choose>
		  </sx:onRecord>
		  <sx:onRecord recordType="SwapFloatingLeg">
			<swapLeg>
			  <sx:fieldAttributeMap field="style" attribute="style"/>
			  <sx:fieldElementMap field="side" element="side"/>
			  <maturityDate>
				<sx:fieldAttributeMap field="maturityDate" attribute="original"/>
			  	<sx:choose>
			  		<sx:when test="maturityDate='2010/04/28'">
			  			<sx:toString value="2001/04/29"/>
			  		</sx:when>
			  	</sx:choose>
			  </maturityDate>
			  <sx:fieldElementMap field="currency" element="currency"/>
			  <sx:fieldElementMap field="index" element="index"/>
			  <sx:fieldElementMap field="notional" element="notional"/>
			</swapLeg>
		  </sx:onRecord>
		  <sx:onRecord recordType="SwapFixedLeg">
			<swapLeg>
			  <sx:fieldAttributeMap field="style" attribute="style"/>
			  <sx:fieldElementMap field="side" element="side"/>
			</swapLeg>
		  </sx:onRecord>
		</trade>
	  </sx:groupBy>
	</exotics>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-exotics.xml -o output/exotics.xml exotics
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Converting flat files with record mappings that have optional elements (optional elements)</title>
      <titleabbrev>optional elements</titleabbrev>
      <indexterm>
        <primary>optional elements</primary>
      </indexterm>
      <indexterm>
        <primary>date/time</primary>
        <secondary>sx:currentDateTime</secondary>
      </indexterm>
      <indexterm>
        <primary>date/time</primary>
        <secondary>sx:formatDateTime</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file to XML by applying an XSLT transform to the canonical XML
representation of each record.
      </para>
      <para>
The input file is shown below.
      </para>
      <programlisting>
        <![CDATA[
262025218|John|Smith|657827168||1|Main Street|London|45879|56|||||
262091012|Jane|Bell||000000000000|105|Penny Lane|Oxford|12345|56|1|Main Street|London|45879|56
]]>
      </programlisting>
      <para>Each line has an id, followed by a first and last name, followed by a customer address, and optionally
a billing address.  If the house number and street of the billing address are empty, the rule is that the
entire billing address be omitted from the XML output.
      </para>
      <para>
The desired output is shown below.
      </para>
      <programlisting>
        <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<mns:Message xmlns:mns="www.abc.com/abc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="www.abc.com/abc abc_v_1.1.xsd ">
   <wf_id>262025218</wf_id>
   <timeStamp>2006-02-11T22:18:21</timeStamp>
   <MessageData>
      <addCustomerRequest>
         <foreName>John</foreName>
         <surName>Smith</surName>
         <custAddress>
            <houseNumber>1</houseNumber>
            <street>Main Street</street>
            <town>London</town>
            <postCode>45879</postCode>
            <country>56</country>
         </custAddress>
      </addCustomerRequest>
   </MessageData>
   <wf_id>262091012</wf_id>
   <timeStamp>2006-02-11T22:18:21</timeStamp>
   <MessageData>
      <addCustomerRequest>
         <foreName>Jane</foreName>
         <surName>Bell</surName>
         <custAddress>
            <houseNumber>105</houseNumber>
            <street>Penny Lane</street>
            <town>Oxford</town>
            <postCode>12345</postCode>
            <country>56</country>
         </custAddress>
         <billAddress>
            <houseNumber>1</houseNumber>
            <street>Main Street</street>
            <town>London</town>
            <postCode>45879</postCode>
            <country>56</country>
         </billAddress>
      </addCustomerRequest>
   </MessageData>
</mns:Message>
]]>
      </programlisting>
      <para>
The following resources script does the transformation.
      </para>
      <programlisting>
        <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="addCustomer">
    <sx:serialize>
      <sx:xsltSerializer>
        <sx:outputProperty name="indent" value="yes"/>
      </sx:xsltSerializer>
      <sx:transform>
        <sx:content ref="addCustomer"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:flatFile id="customerFile">
    <sx:flatFileBody>
      <sx:flatRecordType name="customer">
        <sx:fieldDelimiter value="|"/>
        <sx:delimitedField name="rowid"/>
        <sx:delimitedField name="forename"/>
        <sx:delimitedField name="surname"/>
        <sx:delimitedField name="vatnumber"/>
        <sx:delimitedField name="ninumber"/>
        <sx:delimitedField name="custaddr_house_nr"/>
        <sx:delimitedField name="custaddr_street"/>
        <sx:delimitedField name="custaddr_town"/>
        <sx:delimitedField name="custaddr_postcode"/>
        <sx:delimitedField name="custaddr_country"/>
        <sx:delimitedField name="billaddr_house_nr"/>
        <sx:delimitedField name="billaddr_street"/>
        <sx:delimitedField name="billaddr_town"/>
        <sx:delimitedField name="billaddr_postcode"/>
        <sx:delimitedField name="billaddr_country"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordContent id="addCustomer">
    <sx:flatFileReader>
      <sx:fileSource file="data/optionalElements.txt"/>
      <sx:flatFile ref="customerFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="addCustomerToXmlMapping"/>
  </sx:recordContent>

  <sx:recordMapping id="addCustomerToXmlMapping">
    <mns:Message xmlns:mns="www.abc.com/abc"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="www.abc.com/abc abc_v_1.1.xsd">
      <sx:onRecord>
        <sx:fieldElementMap field="rowid" element="wf_id"/>
        <timeStamp>
          <sx:formatDateTime format = "yyyy-MM-dd'T'HH:mm:ss">
            <sx:currentDateTime/>
          </sx:formatDateTime>
        </timeStamp>
        <sx:transformRecord>
          <sx:xslt>
            <xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
              <xsl:template match="customer">
                <MessageData>
                  <addCustomerRequest>
                    <xsl:element name="foreName">
                      <xsl:value-of select="forename"/>
                    </xsl:element>
                    <xsl:element name="surName">
                      <xsl:value-of select="surname"/>
                    </xsl:element>
                    <custAddress>
                      <xsl:element name="houseNumber">
                        <xsl:value-of select="custaddr_house_nr"/>
                      </xsl:element>
                      <xsl:element name="street">
                        <xsl:value-of select="custaddr_street"/>
                      </xsl:element>
                      <xsl:element name="town">
                        <xsl:value-of select="custaddr_town"/>
                      </xsl:element>
                      <xsl:element name="postCode">
                        <xsl:value-of select="custaddr_postcode"/>
                      </xsl:element>
                      <xsl:element name="country">
                        <xsl:value-of select="custaddr_country"/>
                      </xsl:element>
                    </custAddress>
                    <xsl:if test="string(billaddr_house_nr) and string(billaddr_street)">
                      <billAddress>
                        <xsl:element name="houseNumber">
                          <xsl:value-of select="billaddr_house_nr"/>
                        </xsl:element>
                        <xsl:element name="street">
                          <xsl:value-of select="billaddr_street"/>
                        </xsl:element>
                        <xsl:element name="town">
                          <xsl:value-of select="billaddr_town"/>
                        </xsl:element>
                        <xsl:element name="postCode">
                          <xsl:value-of select="billaddr_postcode"/>
                        </xsl:element>
                        <xsl:element name="country">
                          <xsl:value-of select="billaddr_country"/>
                        </xsl:element>
                      </billAddress>
                    </xsl:if>
                  </addCustomerRequest>
                </MessageData>
              </xsl:template>
            </xsl:transform>
          </sx:xslt>
        </sx:transformRecord>
      </sx:onRecord>
    </mns:Message>
  </sx:recordMapping>

</sx:resources>
]]>
      </programlisting>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-optionalElements.xml  
  -o output/optionalElements.xml optionalElements
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Converting a Java properties file to XML (messages)</title>
      <titleabbrev>properties to XML</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>Java properties</secondary>
      </indexterm>
      <indexterm>
        <primary>record delimiter</primary>
        <secondary>continuation</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
Java properties file to XML.</para>
      <para>
The input file is a Java properties file.
      </para>
      <figure id="messages.properties">
        <title>Input property file messages.properties</title>
        <programlisting>
          <![CDATA[
parser.ope.2=')' or '-[' or '+[' or '&[' is expected.
parser.factor.5=A back reference or an anchor or a lookahead or a lookbehind \
is expected in a conditional pattern.
parser.next.2='?' is not expected.  '(?:' or '(?=' or '(?!' or '(?<' or '(?#' or '(?>'?
#parser.next.3='(?<=' or '(?<!' is expected.
]]>
        </programlisting>
      </figure>
      <para>
This file has a number of features.
        <itemizedlist>
          <listitem>
            <para>The entries are key-value pairs separated by the '=' symbol.</para>
          </listitem>
          <listitem>
            <para>The value in the first line contains an '<![CDATA[&]]>' symbol,
which is a special character in XML, and will be escaped in the output file.</para>
          </listitem>
          <listitem>
            <para>The second line ends with a continuation character.</para>
          </listitem>
          <listitem>
            <para>The value in the third line contains an '=' symbol.</para>
          </listitem>
          <listitem>
            <para>The last line starts with a comment symbol.</para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="messages.xml">
        <title>Output XML file messages.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<messages>
  <parser.ope.2>')' or '-[' or '+[' or '&amp;[' is expected.</parser.ope.2>
  <parser.factor.5>A back reference or an anchor or a lookahead or a lookbehind is expected in a conditional pattern.</parser.factor.5>
  <parser.next.2>'?' is not expected.  '(?:' or '(?=' or '(?!' or '(?&lt;' or '(?#' or '(?&gt;'?</parser.next.2>
</messages>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-messages.xml">
        <title>Resources script resources-messages.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">
   
  <sx:service id="messages">                         
    <sx:serialize>
      <sx:transform>
        <sx:content ref="messages"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>
  
  <sx:recordContent id="messages">
    <sx:flatFileReader>
      <sx:urlSource url="data/messages.properties"/>
      <sx:flatFile>
        <sx:recordDelimiter continuation="\" value="\r\n"/> 
        <sx:recordDelimiter continuation="\" value="\n"/> 
        <sx:commentStarter value="#"/>
        <sx:flatFileBody>
          <sx:flatRecordType name="property">
            <sx:delimitedField name="name">
              <sx:fieldDelimiter value="="/>
            </sx:delimitedField>
            <sx:delimitedField name="value"/>
          </sx:flatRecordType>
        </sx:flatFileBody>
      </sx:flatFile>
    </sx:flatFileReader>

    <sx:recordMapping>
      <messages>
        <sx:onRecord>
          <sx:fieldElementMap field="value" element="{name}"/>
        </sx:onRecord>
      </messages>
    </sx:recordMapping>
  </sx:recordContent>
  
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points about this script.
        <itemizedlist>
          <listitem>
            <para>
The '=' delimiter is associated only with the
              <code>name</code>
field,
not the
              <code>value</code>
field.
            </para>
          </listitem>
          <listitem>
            <para>
There is no delimiter specified for the
              <code>value</code>
field, nor for the record as a whole.
This means that the
              <code>value</code>
field will contain all the text between the first '=' symbol and the
record delimiter, including any more '=' symbols.
            </para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-messages.xml -o output/messages.xml 
    messages
]]>
        </programlisting>
      </para>
    </section>

    <section>
      <title>Transforming a Java properties file with extra name field delimiters to produce nested tags (nested tags 1)</title>
      <titleabbrev>properties to XML (grouped)</titleabbrev>
      <indexterm>
        <primary>group</primary>
        <secondary>by</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>Java properties</secondary>
      </indexterm>
      <indexterm>
        <primary>record delimiter</primary>
        <secondary>continuation</secondary>
      </indexterm>
      <para>
This example shows one way to write a resources script that will convert a
Java properties file to XML with nested tags.</para>
      <para>
The input file is a Java properties file.
      </para>
      <figure id="multipart-keys.properties" xreflabel="properties input file">
        <title>Input property file multipart-keys.properties</title>
        <programlisting>
          <![CDATA[
image.text.info1=hello world 1 
image.text.info2=hello \
world 2 
image.text.info3=hello world 3
]]>
        </programlisting>
      </figure>
      <para>
This file has a number of features.
        <itemizedlist>
          <listitem>
            <para>The entries are key-value pairs separated by an '=' symbol.</para>
          </listitem>
          <listitem>
            <para>Each name consists of three parts separated by a '.' symbol</para>
          </listitem>
          <listitem>
            <para>The second line ends with a continuation character.</para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="nested-tags1.xml" xreflabel="XML output file">
        <title>Output XML file nested-tags1.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<messages>
  <image>
    <text>
      <info1>hello world 1</info1>
      <info2>hello world 2</info2>
      <info3>hello world 3</info3>
    </text>
  </image>
</messages>
]]>
        </programlisting>
      </figure>
      <para>
Note that each level of nesting corresponds to separate part of the key.
      </para>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-messages.xml">
        <title>Resources script resources-props2nested1.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="messages">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="messages"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="messages">

    <sx:flatFileReader>
      <sx:flatFile>
        <sx:commentStarter value="#"/>
        <sx:commentStarter value="//"/>
        <sx:recordDelimiter continuation="\" value="\r\n"/>
        <sx:recordDelimiter continuation="\" value="\n"/>
        <sx:flatFileBody>
          <sx:flatRecordType name="property">
            <sx:delimitedField name="key1">
              <sx:fieldDelimiter value="."/>
            </sx:delimitedField>
            <sx:delimitedField name="key2">
              <sx:fieldDelimiter value="."/>
            </sx:delimitedField>
            <sx:delimitedField name="key3">
              <sx:fieldDelimiter value="="/>
            </sx:delimitedField>
            <sx:delimitedField name="value"/>
          </sx:flatRecordType>
        </sx:flatFileBody>
      </sx:flatFile>
    </sx:flatFileReader>

    <sx:recordMapping>
      <messages>
        <sx:groupBy fields="key1">
          <sx:elementMap element="{key1}">
            <sx:groupBy fields="key2 key2">
              <sx:elementMap element="{key2}">
                <sx:onRecord>
                  <sx:fieldElementMap field="value" element="{key3}"/>
                </sx:onRecord>
              </sx:elementMap>
            </sx:groupBy>
          </sx:elementMap>
        </sx:groupBy>
      </messages>
    </sx:recordMapping>

  </sx:recordContent>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
This script relies on reading each record as four fields.
        <itemizedlist>
          <listitem>
            <phrase>
              <code>key1</code>
is terminated with a '.' delimiter</phrase>
          </listitem>
          <listitem>
            <phrase>
              <code>key2</code>
is terminated with a '.' delimiter</phrase>
          </listitem>
          <listitem>
            <phrase>
              <code>key3</code>
is terminated with an '=' delimiter</phrase>
          </listitem>
          <listitem>
            <phrase>
              <code>value</code>
is terminated with a record delimiter</phrase>
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i data/multipart-keys.properties 
    -o output/nested-tags1.xml -r resources-props2nested1.xml messages
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Transforming a Java properties file with name subfield delimiters to produce nested tags (nested tags 2)</title>
      <titleabbrev>properties (muti-valued) to XML (grouped)</titleabbrev>
      <indexterm>
        <primary>group</primary>
        <secondary>by</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>Java properties</secondary>
      </indexterm>
      <para>
This example shows another way to write a resources script that will convert a
Java properties file to XML with nested tags.
      </para>
      <para>
The
        <xref linkend="multipart-keys.properties"/>
and the desired
        <xref linkend="nested-tags1.xml"/>
are the same as the previous example.
      </para>
      <para>
This time the resources script is written as follows.
      </para>
      <figure id="resources-messages.xml">
        <title>Resources script resources-props2nested2.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="messages">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="messages"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="messages">

    <sx:flatFileReader>
      <sx:flatFile>
        <sx:commentStarter value="#"/>
        <sx:commentStarter value="//"/>
        <sx:recordDelimiter continuation="\" value="\r\n"/>
        <sx:recordDelimiter continuation="\" value="\n"/>
        <sx:flatFileBody>
          <sx:flatRecordType name="property">
            <sx:delimitedField name="name">
              <sx:fieldDelimiter value="="/>
              <sx:subfieldDelimiter value="."/>
            </sx:delimitedField>
            <sx:delimitedField name="value"/>
          </sx:flatRecordType>
        </sx:flatFileBody>
      </sx:flatFile>
    </sx:flatFileReader>

    <sx:recordMapping>
      <messages>
        <sx:groupBy fields="name[1]">
          <sx:elementMap element="{name[1]}">
            <sx:groupBy fields="name[1] name[2]">
              <sx:elementMap element="{name[2]}">
                <sx:onRecord>
                  <sx:fieldElementMap field="value" element="{name[3]}"/>
                </sx:onRecord>
              </sx:elementMap>
            </sx:groupBy>
          </sx:elementMap>
        </sx:groupBy>
      </messages>
    </sx:recordMapping>

  </sx:recordContent>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
This script relies on reading each record as two fields, a multi-valued name field and a value field.
        <itemizedlist>
          <listitem>
            <phrase>
              <code>name</code>
has three values that may be indexed as 1...3</phrase>
          </listitem>
          <listitem>
            <phrase>
              <code>value</code>
has one value</phrase>
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i data/multipart-keys.properties 
    -o output/nested-tags2.xml -r resources-props2nested2.xml messages
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Reordering a group of records before mapping to XML (multiple summaries)</title>
      <titleabbrev>multiple summaries</titleabbrev>
      <indexterm>
        <primary>records</primary>
        <secondary>reordering</secondary>
      </indexterm>
      <para>
The example below shows how to reorder a group of records
        before mapping them to XML.</para>
      <para>
The input file is shown below.
      </para>
      <programlisting>
        <![CDATA[
HEADER  
S 001 
S 002 
B 001
S 003 
B 002
TRAILER 
]]>
      </programlisting>
      <para>Each 'B' record represents a summary of the 'S' records since the last summary..
      </para>
      <para>
Suppose you want to turn it into the following:.
      </para>
      <programlisting>
        <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<DOCUMENT>
  <HEADER/>
  <B value="001">
    <S value="001"/>
    <S value="002"/>
  </B>
  <B value="003">
    <S value="003"/>
  </B>
  <TRAILER/>
</DOCUMENT>
]]>
      </programlisting>
      <para>
If the summary records came before the details, rather than after, the mapping would be straightforward:
see the examples with sx:innerGroup grouping elements. This suggests reordering the records as they come in.
      </para>
      <para>
The following resources script does the transformation.
      </para>
      <programlisting>
        <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="multipleSummaries">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="multipleSummariesContent"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="multipleSummariesContent">
    <sx:flatFileReader>
      <sx:urlSource url="data/multipleSummaries.txt"/>
      <sx:flatFile ref="multipleSummariesFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="multipleSummariesMapping"/>
  </sx:recordContent>

  <sx:recordMapping id="multipleSummariesMapping">
    <DOCUMENT>
      <sx:groupChoice>

        <sx:innerGroup startTest="sx:current/Header" 
                       endTest="sx:previous/Header">
          <sx:onRecord>
            <HEADER/>
          </sx:onRecord>
        </sx:innerGroup>

        <sx:innerGroup startTest="sx:current/Trailer" 
                       endTest="sx:previous/Trailer">
          <sx:onRecord>
            <TRAILER/>
          </sx:onRecord>                                        
        </sx:innerGroup>

        <sx:innerGroup startTest="sx:current/S" 
                       endTest="sx:previous/B">
          <!-- reorder the records in this group - move the B records to the front -->
          <sx:reorderRecords recordTypes="B S"/>
            <B>
              <sx:fieldAttributeMap field="value" attribute="value"/>
              <sx:onRecord recordType='S'>
                <S>
                  <sx:fieldAttributeMap field="value" attribute="value"/>
                </S>
              </sx:onRecord>
            </B>
        </sx:innerGroup>

      </sx:groupChoice>
    </DOCUMENT>
  </sx:recordMapping>

  <sx:flatFile id="multipleSummariesFile">
    <sx:flatFileBody>
      <sx:fieldDelimiter>                            
        <sx:whitespaceSeparator/>
      </sx:fieldDelimiter>
      <sx:flatRecordTypeChoice>
        <sx:delimitedField name="tag"/>
        <sx:when test="tag='HEADER'">
          <sx:flatRecordType name="Header">
            <sx:delimitedField name="tag"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='TRAILER'">
          <sx:flatRecordType name="Trailer">
            <sx:delimitedField name="tag"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='S'">
          <sx:flatRecordType name="S">
            <sx:delimitedField name="tag"/>
            <sx:delimitedField name="value"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='B'">
          <sx:flatRecordType name="B">
            <sx:delimitedField name="tag"/>
            <sx:delimitedField name="value"/>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

</sx:resources>
]]>
      </programlisting>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-multipleSummaries.xml  
  -o output/multipleSummaries.xml multipleSummaries
]]>
        </programlisting>
      </para>
    </section>
  </section>
  <section>
    <title>Delimited Fields, Multiple Record Types, Repeating Groups</title>
    <section>
      <title>Mapping multiple repeating groups to XML (students-delim)</title>
      <titleabbrev>students-delim</titleabbrev>
      <indexterm>
        <primary>repeating groups</primary>
        <secondary>delimited</secondary>
      </indexterm>
      <para>
Suppose you have the following delimited file of students, their course grades, and their addresses.
      </para>
      <figure id="students-delim.txt" xreflabel="students-delim.txt flat file">
        <title>Input flat file students-delim.txt</title>
        <programlisting>
          <![CDATA[
JANE^ENGL^C-~MATH^A+|1972^BLUE^CHICAGO^IL~ATLANTA^GA
]]>
        </programlisting>
      </figure>
      <para>
The file has the following layout.
      </para>
      <informaltable colsep="0">
        <tr>
          <td>name</td>
          <td>the field delimiter ^ defines the end of the field</td>
        </tr>
        <tr>
          <td>subject-grade</td>
          <td>repeating group, repeating segments are separated by the repeat delimiter ~, the segment delimiter | defines the end of the group</td>
        </tr>
        <tr>
          <td>year-born</td>
          <td>the field delimiter ^ defines the end of the field</td>
        </tr>
        <tr>
          <td>favorite-color</td>
          <td>the field delimiter ^ defines the end of the field</td>
        </tr>
        <tr>
          <td>address</td>
          <td>repeating group, repeating segments are separated by the repeat delimiter ~, the segment delimiter | defines the end of the group</td>
        </tr>
      </informaltable>
      <para>
You want the XML output to look as follows.
      </para>
      <figure id="students-fix.xml">
        <title>Output XML file students-fix.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<StudentGrades>
  <StudentGrade>
    <Name>JANE</Name>
    <SubjectGrade>
      <Subject>ENGL</Subject>
      <Grade>C-</Grade>
    </SubjectGrade>
    <SubjectGrade>
      <Subject>MATH</Subject>
      <Grade>A+</Grade>
    </SubjectGrade>
    <YearBorn>1972</YearBorn>
    <FavoriteColor>BLUE</FavoriteColor>
    <Address>
      <City>CHICAGO</City>
      <State>IL</State>
    </Address>
    <Address>
      <City>ATLANTA</City>
      <State>GA</State>
    </Address>
  </StudentGrade>
</StudentGrades>
]]>
        </programlisting>
      </figure>
      <para>The required resources script is
      </para>
      <figure id="resources-students-delim.xml">
        <title>Resources script resources-students-delim.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="students">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="students-content"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="students-content">
    <sx:flatFileReader>
      <sx:flatFile ref="students-file"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="students-mapping"/>
  </sx:recordContent>

  <sx:flatFile id="students-file">
    <sx:flatFileBody>
      <sx:flatRecordType name="student">
        <sx:fieldDelimiter value="^"/>                                              
        <sx:repeatDelimiter value="~"/>
        <sx:segmentDelimiter value="|"/>
        <sx:delimitedField name="name"/>
        <sx:repeatingGroup name="grades">
          <sx:flatRecordType name="subject-grade">
            <sx:fieldDelimiter value="^"/>                                              
            <sx:delimitedField name="subject"/>
            <sx:delimitedField name="grade"/>
          </sx:flatRecordType>
        </sx:repeatingGroup>
        <sx:delimitedField name="year-born"/>
        <sx:delimitedField name="favorite-color"/>
        <sx:repeatingGroup name="addresses">
          <sx:flatRecordType name="address">
            <sx:fieldDelimiter value="^"/>                                              
            <sx:delimitedField name="city"/>
            <sx:delimitedField name="state"/>
          </sx:flatRecordType>
        </sx:repeatingGroup>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="students-mapping">
    <StudentGrades>
      <sx:onRecord>
        <StudentGrade>
          <sx:fieldElementMap field="name" element="Name"/>
          <sx:subrecordMapping repeatingGroup="grades">
            <sx:onRecord>
              <SubjectGrade>
                <sx:fieldElementMap field="subject" element="Subject"/>
                <sx:fieldElementMap field="grade" element="Grade"/>
              </SubjectGrade>
            </sx:onRecord>
          </sx:subrecordMapping>
          <sx:fieldElementMap field="year-born" element="YearBorn"/>
          <sx:fieldElementMap field="favorite-color" element="FavoriteColor"/>
          <sx:subrecordMapping repeatingGroup="addresses">
            <sx:onRecord>
              <Address>
                <sx:fieldElementMap field="city" element="City"/>
                <sx:fieldElementMap field="state" element="State"/>
              </Address>
            </sx:onRecord>
          </sx:subrecordMapping>
        </StudentGrade>
      </sx:onRecord>
    </StudentGrades>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml  -r resources-students-delim.xml -i data/students-delim.txt -o output/students-delim.xml 
    students
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Mapping a sequence of nested repeating groups to XML (invoice)</title>
      <titleabbrev>invoice</titleabbrev>
      <indexterm>
        <primary>repeating groups</primary>
        <secondary>delimited</secondary>
      </indexterm>
      <indexterm>
        <primary>repeating groups</primary>
        <secondary>nested</secondary>
      </indexterm>
      <para>
Suppose you have the following data file.
      </para>
      <figure id="invoice.txt" xreflabel="invoice.txt flat file">
        <title>Input flat file invoice.txt</title>
        <programlisting>
          <![CDATA[
12|2007-02-02|DocType|} 
SndId|SndName|SndAddress|SndZip|} 
RecId|RecName|RecAddress|RecZip|} 
~ 
1|Item 1|2|Kg|150|300|} 
2|Item 2|2|Kg|350|700|} 
3|Item 3|1|$|50|50|} 
4|Item 4|10|Unt|30|100|} 
~ 
1|Ref 1|Doc 1|Text|} 
2|Ref 2|Doc 2|Text|} 
~ 
1|Disc 1|Item 1|} 
2|Disc 2|Item 2|} 
3|Disc 3|Item 3|} 
~ 
Code a|Value 1|} 
Code z|Value 3|} 
Code x|Value 2|} 
Code w|Value 2|} 
Code y|Value 1|}
~ 
!
]]>
        </programlisting>
      </figure>
      <para>The file has
        <code>n</code>
sections separated by the "~" character.  The first section has several non repeating records separated by a "}".
But after that, there are 4 repeating sections separated by the same "~" as above.  Each repeating section starts where the previous one ends.
      </para>
      <para>The character "!" as the first character in the last line indicates the end of the data.
      </para>
      <para>
You want the XML output to look as follows.
      </para>
      <figure id="invoice.xml">
        <title>Output XML file invoice.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<InvoiceDocument>
   <Header>
      <DocId>
         <Id>12</Id>
         <DocDate>2007-02-02</DocDate>
         <DocumentType>DocType</DocumentType>
      </DocId>
      <Sender>
         <SenderPassport>SndId</SenderPassport>
         <SenderFullName>SndName</SenderFullName>
         <SenderAddress>SndAddress</SenderAddress>
         <SenderZip>SndZip</SenderZip>
      </Sender>
      <Recipient>
         <RecipientPassport>RecId</RecipientPassport>
         <RecipientFullName>RecName</RecipientFullName>
         <RecipientAddress>RecAddress</RecipientAddress>
         <RecipientZip>RecZip</RecipientZip>
      </Recipient>
   </Header>
   <Detail>
      <Item>1</Item>
      <Description>Item 1</Description>
      <Quantity>2</Quantity>
      <Unit>Kg</Unit>
      <ItemPrice>150</ItemPrice>
      <TotalPrice>300</TotalPrice>
   </Detail>
   <Detail>
      <Item>2</Item>
      <Description>Item 2</Description>
      <Quantity>2</Quantity>
      <Unit>Kg</Unit>
      <ItemPrice>350</ItemPrice>
      <TotalPrice>700</TotalPrice>
   </Detail>
   <Detail>
      <Item>3</Item>
      <Description>Item 3</Description>
      <Quantity>1</Quantity>
      <Unit>$</Unit>
      <ItemPrice>50</ItemPrice>
      <TotalPrice>50</TotalPrice>
   </Detail>
   <Detail>
      <Item>4</Item>
      <Description>Item 4</Description>
      <Quantity>10</Quantity>
      <Unit>Unt</Unit>
      <ItemPrice>30</ItemPrice>
      <TotalPrice>100</TotalPrice>
   </Detail>
   <Reference>
      <RefId>1</RefId>
      <RefType>Ref 1</RefType>
      <RefDoc>Doc 1</RefDoc>
      <RefText>Text</RefText>
   </Reference>
   <Reference>
      <RefId>2</RefId>
      <RefType>Ref 2</RefType>
      <RefDoc>Doc 2</RefDoc>
      <RefText>Text</RefText>
   </Reference>
   <Discount>
      <DiscId>1</DiscId>
      <DiscDescription>Disc 1</DiscDescription>
      <DiscItem>Item 1</DiscItem>
   </Discount>
   <Discount>
      <DiscId>2</DiscId>
      <DiscDescription>Disc 2</DiscDescription>
      <DiscItem>Item 2</DiscItem>
   </Discount>
   <Discount>
      <DiscId>3</DiscId>
      <DiscDescription>Disc 3</DiscDescription>
      <DiscItem>Item 3</DiscItem>
   </Discount>
   <Code>
      <Code>Code a</Code>
      <Value>Value 1</Value>
   </Code>
   <Code>
      <Code>Code z</Code>
      <Value>Value 3</Value>
   </Code>
   <Code>
      <Code>Code x</Code>
      <Value>Value 2</Value>
   </Code>
   <Code>
      <Code>Code w</Code>
      <Value>Value 2</Value>
   </Code>
   <Code>
      <Code>Code y</Code>
      <Value>Value 1</Value>
   </Code>
</InvoiceDocument>
]]>
        </programlisting>
      </figure>
      <para>The required resources script is
      </para>
      <figure id="resources-invoice.xml">
        <title>Resources script resources-invoice.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="invoice">
    <sx:serialize>
      <sx:xsltSerializer>
        <sx:outputProperty name="indent" value="yes"/>
      </sx:xsltSerializer>
      <sx:transform>
        <sx:content ref="invoice-content"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="invoice-content">
    <sx:flatFileReader>
      <sx:flatFile ref="invoice-file"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="invoice-mapping"/>
  </sx:recordContent>

  <sx:flatFile id="invoice-file">
    <sx:recordDelimiter value="\r\n!"/>
    <sx:recordDelimiter value="\n!"/>
    <sx:flatFileBody>
      <sx:flatRecordType name="invoice" omitFinalRepeatDelimiter="false">
        <sx:repeatDelimiter value="~"/>
        <sx:repeatingGroup name="Header" count="1">
          <sx:flatRecordType name="Header">
            <sx:fieldDelimiter value="|"/>
            <sx:repeatDelimiter value="}"/>
            <!--sx:segmentDelimiter value="~"/-->
            <sx:repeatingGroup name="Document" count="1">
              <sx:flatRecordType name="Doc">
                <sx:delimitedField name="Id"/>
                <sx:delimitedField name="DocDate"/>
                <sx:delimitedField name="DocumentType"/>
              </sx:flatRecordType>
            </sx:repeatingGroup>
            <sx:repeatingGroup name="Sender" count="1">
              <sx:flatRecordType name="Sender">
                <sx:delimitedField name="SenderPassport"/>
                <sx:delimitedField name="SenderFullName"/>
                <sx:delimitedField name="SenderAddress"/>
                <sx:delimitedField name="SenderZip"/>
              </sx:flatRecordType>
            </sx:repeatingGroup>
            <sx:repeatingGroup name="Recipient" count="1">
              <sx:flatRecordType name="Recipient">
                <sx:delimitedField name="RecipientPassport"/>
                <sx:delimitedField name="RecipientFullName"/>
                <sx:delimitedField name="RecipientAddress"/>
                <sx:delimitedField name="RecipientZip"/>
              </sx:flatRecordType>
            </sx:repeatingGroup>
          </sx:flatRecordType>
        </sx:repeatingGroup>

        <sx:repeatingGroup name="Detail" count="1">
          <sx:flatRecordType name="Detail">
            <sx:fieldDelimiter value="|"/>
            <sx:repeatDelimiter value="}"/>
            <sx:repeatingGroup name="Item">
              <sx:flatRecordType name="Item">
                <sx:delimitedField name="Item"/>
                <sx:delimitedField name="Description"/>
                <sx:delimitedField name="Quantity"/>
                <sx:delimitedField name="Unit"/>
                <sx:delimitedField name="ItemPrice"/>
                <sx:delimitedField name="TotalPrice"/>
              </sx:flatRecordType>
            </sx:repeatingGroup>
          </sx:flatRecordType>
        </sx:repeatingGroup>

        <sx:repeatingGroup name="Reference" count="1">
          <sx:flatRecordType name="Reference">
            <sx:fieldDelimiter value="|"/>
            <sx:repeatDelimiter value="}"/>
            <sx:segmentDelimiter value="~"/>
            <sx:repeatingGroup name="Ref">
              <sx:flatRecordType name="Ref">
                <sx:delimitedField name="RefId"/>
                <sx:delimitedField name="RefType"/>
                <sx:delimitedField name="RefDoc"/>
                <sx:delimitedField name="RefText"/>
              </sx:flatRecordType>
            </sx:repeatingGroup>
          </sx:flatRecordType>
        </sx:repeatingGroup>

        <sx:repeatingGroup name="Discount" count="1">
          <sx:flatRecordType name="Discount">
            <sx:fieldDelimiter value="|"/>
            <sx:repeatDelimiter value="}"/>
            <sx:segmentDelimiter value="~"/>
            <sx:repeatingGroup name="Disc">
              <sx:flatRecordType name="Disc">
                <sx:delimitedField name="DiscId"/>
                <sx:delimitedField name="DiscDescription"/>
                <sx:delimitedField name="DiscItem"/>
              </sx:flatRecordType>
            </sx:repeatingGroup>
          </sx:flatRecordType>
        </sx:repeatingGroup>

        <sx:repeatingGroup name="Codes" count="1">
          <sx:flatRecordType name="Codes">
            <sx:fieldDelimiter value="|"/>
            <sx:repeatDelimiter value="}"/>
            <sx:segmentDelimiter value="~"/>
            <sx:repeatingGroup name="Code">
              <sx:flatRecordType name="Code">
                <sx:delimitedField name="Code"/>
                <sx:delimitedField name="Value"/>
              </sx:flatRecordType>
            </sx:repeatingGroup>
          </sx:flatRecordType>
        </sx:repeatingGroup>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="invoice-mapping">
    <InvoiceDocument>
      <sx:onRecord>
        <sx:subrecordMapping repeatingGroup="Header">
          <sx:onRecord>
            <Header>
              <sx:subrecordMapping repeatingGroup="Document">
                <sx:onRecord>
                  <DocId>
                    <sx:fieldElementMap field="Id" element="Id"/>
                    <sx:fieldElementMap field="DocDate" element="DocDate"/>
                    <sx:fieldElementMap field="DocumentType" element="DocumentType"/>
                  </DocId>
                </sx:onRecord>
              </sx:subrecordMapping>
              <sx:subrecordMapping repeatingGroup="Sender">
                <sx:onRecord>
                  <Sender>
                    <sx:fieldElementMap field="SenderPassport" element="SenderPassport"/>
                    <sx:fieldElementMap field="SenderFullName" element="SenderFullName"/>
                    <sx:fieldElementMap field="SenderAddress" element="SenderAddress"/>
                    <sx:fieldElementMap field="SenderZip" element="SenderZip"/>
                  </Sender>
                </sx:onRecord>
              </sx:subrecordMapping>
              <sx:subrecordMapping repeatingGroup="Recipient">
                <sx:onRecord>
                  <Recipient>
                    <sx:fieldElementMap field="RecipientPassport" element="RecipientPassport"/>
                    <sx:fieldElementMap field="RecipientFullName" element="RecipientFullName"/>
                    <sx:fieldElementMap field="RecipientAddress" element="RecipientAddress"/>
                    <sx:fieldElementMap field="RecipientZip" element="RecipientZip"/>
                  </Recipient>
                </sx:onRecord>
              </sx:subrecordMapping>
            </Header>
          </sx:onRecord>
        </sx:subrecordMapping>

        <sx:subrecordMapping repeatingGroup="Detail">
          <sx:onRecord>
            <sx:subrecordMapping repeatingGroup="Item">
              <sx:onRecord>
                <Detail>
                  <sx:fieldElementMap field="Item" element="Item"/>
                  <sx:fieldElementMap field="Description" element="Description"/>
                  <sx:fieldElementMap field="Quantity" element="Quantity"/>
                  <sx:fieldElementMap field="Unit" element="Unit"/>
                  <sx:fieldElementMap field="ItemPrice" element="ItemPrice"/>
                  <sx:fieldElementMap field="TotalPrice" element="TotalPrice"/>
                </Detail>
              </sx:onRecord>
            </sx:subrecordMapping>
          </sx:onRecord>
        </sx:subrecordMapping>

        <sx:subrecordMapping repeatingGroup="Reference">
          <sx:onRecord>
            <sx:subrecordMapping repeatingGroup="Ref">
              <sx:onRecord>
                <Reference>
                  <sx:fieldElementMap field="RefId" element="RefId"/>
                  <sx:fieldElementMap field="RefType" element="RefType"/>
                  <sx:fieldElementMap field="RefDoc" element="RefDoc"/>
                  <sx:fieldElementMap field="RefText" element="RefText"/>
                </Reference>
              </sx:onRecord>
            </sx:subrecordMapping>
          </sx:onRecord>
        </sx:subrecordMapping>

        <sx:subrecordMapping repeatingGroup="Discount">
          <sx:onRecord>
            <sx:subrecordMapping repeatingGroup="Disc">
              <sx:onRecord>
                <Discount>
                  <sx:fieldElementMap field="DiscId" element="DiscId"/>
                  <sx:fieldElementMap field="DiscDescription" element="DiscDescription"/>
                  <sx:fieldElementMap field="DiscItem" element="DiscItem"/>
                </Discount>
              </sx:onRecord>
            </sx:subrecordMapping>
          </sx:onRecord>
        </sx:subrecordMapping>

        <sx:subrecordMapping repeatingGroup="Codes">
          <sx:onRecord>
            <sx:subrecordMapping repeatingGroup="Code">
              <sx:onRecord>
                <Code>
                  <sx:fieldElementMap field="Code" element="Code"/>
                  <sx:fieldElementMap field="Value" element="Value"/>
                </Code>
              </sx:onRecord>
            </sx:subrecordMapping>
          </sx:onRecord>
        </sx:subrecordMapping>
      </sx:onRecord>
    </InvoiceDocument>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
The idea is to map all the data up to the terminating "!" as one record, and to structure the record as a sequence of nested
repeating groups.
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml  -r resources-invoice.xml -i data/invoice.txt -o output/invoice.xml 
    invoice
]]>
        </programlisting>
      </para>
    </section>
  </section>
  <section>
    <title>EDI Examples</title>
    <section>
      <title>EDI to XML (comptest)</title>
      <titleabbrev>edi to XML</titleabbrev>
      <indexterm>
        <primary>edi</primary>
      </indexterm>
      <indexterm>
        <primary>repeating groups</primary>
      </indexterm>
      <para>
The example below shows how to convert a
composite field in an edi file to XML.
      </para>
      <para>
The input file is an edi file.
      </para>
      <figure id="comptest.txt">
        <title>Input edi file comptest.txt</title>
        <programlisting>
          <![CDATA[
BKG+1++4+Y:1:B:0:M:0:L:1'
]]>
        </programlisting>
      </figure>
      <para>
This file has a number of features.
        <itemizedlist>
          <listitem>
            <para>The segment delimiter "'" terminates the segment.</para>
          </listitem>
          <listitem>
            <para>The field delimiter "+" terminates a field.</para>
          </listitem>
          <listitem>
            <para>Composite fields are delimited with ":".</para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="messages.xml">
        <title>Output XML file messages.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<edifact>
  <segment segmentType="BKG">
    <flightSegmentNumber>1</flightSegmentNumber>
    <accessID/>
    <bookingCodeCount>4</bookingCodeCount>
    <C704>
      <bookingCode>Y</bookingCode>
      <seatAvailabilityCount>1</seatAvailabilityCount>
    </C704>
    <C704>
      <bookingCode>B</bookingCode>
      <seatAvailabilityCount>0</seatAvailabilityCount>
    </C704>
    <C704>
      <bookingCode>M</bookingCode>
      <seatAvailabilityCount>0</seatAvailabilityCount>
    </C704>
    <C704>
      <bookingCode>L</bookingCode>
      <seatAvailabilityCount>1</seatAvailabilityCount>
    </C704>
  </segment>
</edifact>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-comptest.xml">
        <title>Resources script resources-comptest.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="edifact">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="edifact"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="edifact">
    <sx:flatFileReader>
      <sx:flatFile ref="edifactFlatFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="edifactToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="edifactFlatFile">
    <sx:recordDelimiter value="'"/>
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:fieldDelimiter value="+"/>
        <sx:delimitedField name="segmentType"/>
        <!-- edifact3 - Body Segments.-->
        <!-- BKG BOOKING CODE DATA .-->
        <sx:when test="segmentType='BKG'">
          <sx:flatRecordType name='BKG'>
            <sx:fieldDelimiter value="+"/>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="flightSegmentNumber"/>
            <sx:delimitedField name="accessID"/>
            <sx:delimitedField name="bookingCodeCount"/>
            <sx:repeatingGroup name="booking" count="{bookingCodeCount}">
              <sx:flatRecordType name="C704">
                <sx:fieldDelimiter value=":"/>
                <sx:delimitedField name="bookingCode">
                </sx:delimitedField>
                <sx:delimitedField name="seatAvailabilityCount">
                </sx:delimitedField>
              </sx:flatRecordType>
            </sx:repeatingGroup>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="edifactToXmlMapping">
    <edifact>
      <!-- edifact3 - Body Segments.-->
      <!-- BKG BOOKING CODE DATA.-->
      <sx:onRecord recordType="BKG">
        <sx:elementMap element="segment">
          <sx:fieldAttributeMap field="segmentType" attribute="segmentType"/>
          <sx:fieldElementMap field="flightSegmentNumber" element="flightSegmentNumber"/>
          <sx:fieldElementMap field="accessID" element="accessID"/>
          <sx:fieldElementMap field="bookingCodeCount" element="bookingCodeCount"/>
          <sx:subrecordMapping repeatingGroup="booking">
            <sx:onRecord recordType="C704">
              <C704>
                <sx:fieldElementMap field="bookingCode" element="bookingCode"/>
                <sx:fieldElementMap field="seatAvailabilityCount" element="seatAvailabilityCount"/>
              </C704>
            </sx:onRecord>
          </sx:subrecordMapping>
        </sx:elementMap>
      </sx:onRecord>
    </edifact>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points about this script.
        <itemizedlist>
          <listitem>
            <para>
All the values of the composite field are put in the multiple valued field "C704".
            </para>
          </listitem>
          <listitem>
            <para>
The sx:repeatingGroup element allows us to map these values, repeated two at a time,
named as
              <code>bookingCode</code>
and
              <code>seatAvailabilityCount</code>
.
            </para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i data/comptest.txt -r resources-comptest.xml 
  -o output/comptest.xml edifact
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>EDI to XML with Escaped Delimiters (Invoic96A)</title>
      <titleabbrev>Invoice96A</titleabbrev>
      <indexterm>
        <primary>edi</primary>
      </indexterm>
      <indexterm>
        <primary>repeating groups</primary>
      </indexterm>
      <para>
The example below shows how to convert a
composite field in an edi file to XML.
      </para>
      <para>
The input file is an edi file.
      </para>
      <figure id="invoic96A.txt">
        <title>Input edi file invoic96A.txt</title>
        <programlisting>
          <![CDATA[
UNB+UNOA:3+0000008033253:14+01534730278:ZZ+080130:0000+04000020++++++1'
UNH+1+INVOIC:D:96A:UN:EAN008'
BGM+381+1000322+9'
DTM+137:20080130:102'
NAD+SU+++COMPANY XXXX ?+ YYYY+VIA ROMA, 1+CITTA?' DI?: GENOVA+GE+16163+IT'
RFF+VA:05577790207'
CUX+2:EUR:4+3'
PAT+10E+ZZZ:::BONIFICO BANCARIO 90 GG D.F.+5:1:D:090'
DTM+13:20080430:102'
LIN+1+L02+8026495011408:EN'
IMD+B++TU:::BAGUETTE PREC. GR.280 40PZ'
QTY+47:5.000:PCE'
QTY+59:40.000:PCE'
MOA+203:54.130:EUR:4'
PRI+AAA:10.830::::PCE'
UNS+S'
MOA+125:54.130'
UNT+46+1'
UNZ+1+04000020'
]]>
        </programlisting>
      </figure>
      <para>
This file has a number of features.
        <itemizedlist>
          <listitem>
            <para>Records are terminated with <code>'</code></para>
          </listitem>
          <listitem>
            <para>Fields are terminated with <code>+</code></para>
          </listitem>
          <listitem>
            <para>Subfields are terminated with <code>:</code></para>
          </listitem>
          <listitem>
            <para>The character ? is used as an escape character. For example, 
              <code>COMPANY?: XXXX?+YYYY+</code> will be interpreted as: 
<code>COMPANY: XXXX+YYYY</code> 
              </para>
          </listitem>
          <listitem>Sometimes the input file could be formatted with a fixed 80 
            column width.  Linefeed characters should be stripped.
          </listitem>
        </itemizedlist>
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="invoic96A.xml">
        <title>Output XML file invoic96A.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Invoic96A>
   <UNB>
      <segmentType>UNB</segmentType>
   </UNB>
   <UNH>
      <segmentType>UNH</segmentType>
      <DE0062>1</DE0062>
      <S009>
         <S009>
            <DE0065>INVOIC</DE0065>
            <DE0052>D</DE0052>
            <DE0054>96A</DE0054>
            <DE0051>UN</DE0051>
            <DE0057>EAN008</DE0057>
         </S009>
      </S009>
      <DE0068/>
   </UNH>
   <BGM>
      <segmentType>BGM</segmentType>
      <C002>
         <C002>
            <DE1001>381</DE1001>
            <DE1131/>
            <DE3055/>
            <DE1000/>
         </C002>
      </C002>
      <DE1004>1000322</DE1004>
      <DE1225>9</DE1225>
      <DE4343/>
   </BGM>
   <DTM>
      <segmentType>DTM</segmentType>
      <C507>
         <C507>
            <DE2005>137</DE2005>
            <DE2380>20080130</DE2380>
            <DE2379>102</DE2379>
         </C507>
      </C507>
   </DTM>
   <NAD>
      <segmentType>NAD</segmentType>
      <DE3035>SU</DE3035>
      <C080>
         <C080>
            <DE3036-1>COMPANY XXXX + YYYY</DE3036-1>
            <DE3036-2/>
            <DE3036-3/>
            <DE3036-4/>
            <DE3036-5/>
            <DE3045/>
         </C080>
      </C080>
      <C059>
         <C059>
            <DE3042-1>VIA ROMA, 1</DE3042-1>
            <DE3042-2/>
            <DE3042-3/>
            <DE3042-4/>
         </C059>
      </C059>
      <DE3164>CITTA' DI: GENOVA</DE3164>
      <DE3229>GE</DE3229>
      <DE3251>16163</DE3251>
      <DE3207>IT</DE3207>
   </NAD>
   <RFF>
      <segmentType>RFF</segmentType>
      <C506>
         <C506>
            <DE1153>VA</DE1153>
            <DE1154>05577790207</DE1154>
            <DE1156/>
            <DE4000/>
         </C506>
      </C506>
   </RFF>
   <CUX>
      <segmentType>CUX</segmentType>
      <C504>
         <C504>
            <DE6347>2</DE6347>
            <DE6345>EUR</DE6345>
            <DE6343>4</DE6343>
            <DE6348/>
         </C504>
         <C504>
            <DE6347>3</DE6347>
            <DE6345/>
            <DE6343/>
            <DE6348/>
         </C504>
      </C504>
      <DE5402/>
      <DE6341/>
   </CUX>
   <PAT>
      <segmentType>PAT</segmentType>
      <DE4279>10E</DE4279>
      <C110>
         <C110>
            <DE4277>ZZZ</DE4277>
            <DE1131/>
            <DE3055/>
            <DE4276-1>BONIFICO BANCARIO 90 GG D.F.</DE4276-1>
            <DE4276-2/>
         </C110>
      </C110>
      <C112>
         <C112>
            <DE2475>5</DE2475>
            <DE2009>1</DE2009>
            <DE2151>D</DE2151>
            <DE2152>090</DE2152>
         </C112>
      </C112>
   </PAT>
   <DTM>
      <segmentType>DTM</segmentType>
      <C507>
         <C507>
            <DE2005>13</DE2005>
            <DE2380>20080430</DE2380>
            <DE2379>102</DE2379>
         </C507>
      </C507>
   </DTM>
   <LIN>
      <segmentType>LIN</segmentType>
      <DE1082>1</DE1082>
      <DE1229>L02</DE1229>
      <C212>
         <C212>
            <DE7140>8026495011408</DE7140>
            <DE7143>EN</DE7143>
            <DE1131/>
            <DE3055/>
         </C212>
      </C212>
      <DE1222/>
      <DE7083/>
   </LIN>
   <IMD>
      <segmentType>IMD</segmentType>
      <DE7077>B</DE7077>
      <DE7081/>
      <C273>
         <C273>
            <DE7009>TU</DE7009>
            <DE1131/>
            <DE3055/>
            <DE7008-1>BAGUETTE PREC. GR.280 40PZ</DE7008-1>
            <DE7008-2/>
            <DE3435/>
         </C273>
      </C273>
      <DE7383/>
   </IMD>
   <QTY>
      <segmentType>QTY</segmentType>
      <C186>
         <C186>
            <DE6063>47</DE6063>
            <DE6060>5.000</DE6060>
            <DE6411>PCE</DE6411>
         </C186>
      </C186>
   </QTY>
   <QTY>
      <segmentType>QTY</segmentType>
      <C186>
         <C186>
            <DE6063>59</DE6063>
            <DE6060>40.000</DE6060>
            <DE6411>PCE</DE6411>
         </C186>
      </C186>
   </QTY>
   <MOA>
      <segmentType>MOA</segmentType>
      <C516>
         <C516>
            <DE5025>203</DE5025>
            <DE5004>54.130</DE5004>
            <DE6345>EUR</DE6345>
            <DE6343>4</DE6343>
            <DE4405/>
         </C516>
      </C516>
   </MOA>
   <PRI>
      <segmentType>PRI</segmentType>
      <C509>
         <C509>
            <DE5125>AAA</DE5125>
            <DE5118>10.830</DE5118>
            <DE5375/>
            <DE5387/>
            <DE5284/>
            <DE6411>PCE</DE6411>
         </C509>
      </C509>
      <DE5213/>
   </PRI>
   <UNS>
      <segmentType>UNS</segmentType>
      <DE0081>S</DE0081>
   </UNS>
   <MOA>
      <segmentType>MOA</segmentType>
      <C516>
         <C516>
            <DE5025>125</DE5025>
            <DE5004>54.130</DE5004>
            <DE6345/>
            <DE6343/>
            <DE4405/>
         </C516>
      </C516>
   </MOA>
   <UNT>
      <segmentType>UNT</segmentType>
      <DE0074>46</DE0074>
      <DE0062>1</DE0062>
   </UNT>
   <UNZ>
      <segmentType>UNZ</segmentType>
      <F0036>1</F0036>
      <F0020>04000020</F0020>
   </UNZ>
</Invoic96A>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-invoic96A.xml">
        <title>Resources script resources-invoic96A.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:msv="http://www.servingxml.com/extensions/msv"
              xmlns:fn="http://www.w3.org/2005/xpath-functions">

  <sx:service id="invoic96A-to-xml">
    <sx:serialize>
      <sx:xsltSerializer>
        <sx:outputProperty name="indent" value="yes"/>
      </sx:xsltSerializer>
      <sx:transform>
        <sx:content ref="Invoic_96A_1"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="Invoic_96A_1" name="Invoic96A">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile ref="edifactFlatFile"/>
      </sx:flatFileReader>
      <sx:discardHandler>
        <sx:log message="{$sx:message}"/>
      </sx:discardHandler>
    </sx:recordStream>
  </sx:recordContent>
	
  <sx:flatFile id="edifactFlatFile">
    <sx:recordDelimiter value="'" escapeCharacter="?"/>
    <!-- If a line is broken with a new line character, strip the new line character -->
    <sx:recordDelimiter value="\r\n" continuationSequence="\r\n"/>
    <sx:recordDelimiter value="\n" continuationSequence="\n"/>
    <!-- if a ' character is found after a ? (?')-->
    <!-- it is an escape sequence and should remain the ' character-->
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:fieldDelimiter value="+" escapeCharacter="?"/>
        <sx:delimitedField name="segmentType"/>

        <sx:when test="segmentType='UNA' or segmentType='UNA:'">
          <sx:flatRecordType name='UNA'>
            <sx:fieldDelimiter value="+" escapeCharacter="?"/>
            <sx:fieldDelimiter value=":" escapeCharacter="?"/>
            <sx:delimitedField name="segmentType"/>
          </sx:flatRecordType>
        </sx:when>

        <sx:when test="segmentType='UNB'">
          <sx:flatRecordType name='UNB'>
            <sx:fieldDelimiter value="+" escapeCharacter="?"/>
            <sx:fieldDelimiter value=":" escapeCharacter="?"/>
            <sx:delimitedField name="segmentType"/>
          </sx:flatRecordType>
        </sx:when>

        <sx:when test="segmentType='UNH'">
          <sx:flatRecordType name='UNH'>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE0062"/>
            <sx:nonrepeatingGroup name="S009">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="S009">
                <sx:delimitedField name="DE0065"/>
                <sx:delimitedField name="DE0052"/>
                <sx:delimitedField name="DE0054"/>
                <sx:delimitedField name="DE0051"/>
                <sx:delimitedField name="DE0057"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE0068"/>
            <sx:nonrepeatingGroup name="S010">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="S010">
                <sx:delimitedField name="DE0070"/>
                <sx:delimitedField name="DE0073"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='BGM'">
          <sx:flatRecordType name='BGM'>
            <sx:delimitedField name="segmentType"/>
            <sx:nonrepeatingGroup name="C002">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C002">
                <sx:delimitedField name="DE1001"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
                <sx:delimitedField name="DE1000"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE1004"/>
            <sx:delimitedField name="DE1225"/>
            <sx:delimitedField name="DE4343"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='DTM'">
          <sx:flatRecordType name='DTM'>
            <sx:delimitedField name="segmentType"/>
            <sx:nonrepeatingGroup name="C507">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C507">
                <sx:delimitedField name="DE2005"/>
                <sx:delimitedField name="DE2380"/>
                <sx:delimitedField name="DE2379"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='PAI'">
          <sx:flatRecordType name='PAI'>
            <sx:delimitedField name="segmentType"/>
            <sx:nonrepeatingGroup name="C534">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C534">
                <sx:delimitedField name="DE4439"/>
                <sx:delimitedField name="DE4431"/>
                <sx:delimitedField name="DE4461"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
                <sx:delimitedField name="DE4435"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='FTX'">
          <sx:flatRecordType name='FTX'>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE4451"/>
            <sx:delimitedField name="DE4453"/>
            <sx:nonrepeatingGroup name="C107">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C107">
                <sx:delimitedField name="DE4441"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:nonrepeatingGroup name="C108">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C108">
                <sx:delimitedField name="DE4440-1"/>
                <sx:delimitedField name="DE4440-2"/>
                <sx:delimitedField name="DE4440-3"/>
                <sx:delimitedField name="DE4440-4"/>
                <sx:delimitedField name="DE4440-5"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE3453"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='NAD'">
          <sx:flatRecordType name='NAD'>
            <sx:fieldDelimiter value="+" escapeCharacter="?"/>
            <sx:fieldDelimiter value=":" escapeCharacter="?"/>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE3035"/>
            <sx:nonrepeatingGroup name="C082">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C082">
                <sx:delimitedField name="DE3039"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:nonrepeatingGroup name="C058">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C058">
                <sx:delimitedField name="DE3124-1"/>
                <sx:delimitedField name="DE3124-2"/>
                <sx:delimitedField name="DE3124-3"/>
                <sx:delimitedField name="DE3124-4"/>
                <sx:delimitedField name="DE3124-5"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:nonrepeatingGroup name="C080">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C080">
                <sx:delimitedField name="DE3036-1"/>
                <sx:delimitedField name="DE3036-2"/>
                <sx:delimitedField name="DE3036-3"/>
                <sx:delimitedField name="DE3036-4"/>
                <sx:delimitedField name="DE3036-5"/>
                <sx:delimitedField name="DE3045"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:nonrepeatingGroup name="C059">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C059">
                <sx:delimitedField name="DE3042-1"/>
                <sx:delimitedField name="DE3042-2"/>
                <sx:delimitedField name="DE3042-3"/>
                <sx:delimitedField name="DE3042-4"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE3164"/>
            <sx:delimitedField name="DE3229"/>
            <sx:delimitedField name="DE3251"/>
            <sx:delimitedField name="DE3207"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='FII'">
          <sx:flatRecordType name='FII'>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE3035"/>
            <sx:nonrepeatingGroup name="C078">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C078">
                <sx:delimitedField name="DE3194"/>
                <sx:delimitedField name="DE3192-1"/>
                <sx:delimitedField name="DE3192-2"/>
                <sx:delimitedField name="DE6345"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:nonrepeatingGroup name="C088">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C088">
                <sx:delimitedField name="DE3433"/>
                <sx:delimitedField name="DE1131-1"/>
                <sx:delimitedField name="DE3055-1"/>
                <sx:delimitedField name="DE3434"/>
                <sx:delimitedField name="DE1131-2"/>
                <sx:delimitedField name="DE3055-2"/>
                <sx:delimitedField name="DE3432"/>
                <sx:delimitedField name="DE3436"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE3207"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='RFF'">
          <sx:flatRecordType name='RFF'>
            <sx:delimitedField name="segmentType"/>
            <sx:nonrepeatingGroup name="C506">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C506">
                <sx:delimitedField name="DE1153"/>
                <sx:delimitedField name="DE1154"/>
                <sx:delimitedField name="DE1156"/>
                <sx:delimitedField name="DE4000"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='CTA'">
          <sx:flatRecordType name='CTA'>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE3139"/>
            <sx:nonrepeatingGroup name="C056">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C056">
                <sx:delimitedField name="DE3413"/>
                <sx:delimitedField name="DE3412"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='COM'">
          <sx:flatRecordType name='COM'>
            <sx:delimitedField name="segmentType"/>
            <sx:nonrepeatingGroup name="C076">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C076">
                <sx:delimitedField name="DE3148"/>
                <sx:delimitedField name="DE3155"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType> 
        </sx:when>
        <sx:when test="segmentType='CUX'">
          <sx:flatRecordType name='CUX'>
            <sx:delimitedField name="segmentType"/>
            <sx:repeatingGroup name="C504" count="2">
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:repeatDelimiter value="+" escapeCharacter="?"/>
              <!--<sx:segmentDelimiter value="+" escapeCharacter="?"/>-->
              <sx:flatRecordType name="C504">
                <sx:delimitedField name="DE6347"/>
                <sx:delimitedField name="DE6345"/>
                <sx:delimitedField name="DE6343"/>
                <sx:delimitedField name="DE6348"/>
              </sx:flatRecordType>
            </sx:repeatingGroup>
            <sx:delimitedField name="DE5402"/>
            <sx:delimitedField name="DE6341"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='PAT'">
          <sx:flatRecordType name='PAT'>
            <sx:fieldDelimiter value="+" escapeCharacter="?"/>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE4279"/>
            <sx:nonrepeatingGroup name="C110">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C110">
                <sx:delimitedField name="DE4277"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
                <sx:delimitedField name="DE4276-1"/>
                <sx:delimitedField name="DE4276-2"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:nonrepeatingGroup name="C112">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C112">
                <sx:delimitedField name="DE2475"/>
                <sx:delimitedField name="DE2009"/>
                <sx:delimitedField name="DE2151"/>
                <sx:delimitedField name="DE2152"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='PCD'">
          <sx:flatRecordType name='PCD'>
            <sx:delimitedField name="segmentType"/>
            <sx:nonrepeatingGroup name="C501">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C501">
                <sx:delimitedField name="DE5245"/>
                <sx:delimitedField name="DE5482"/>
                <sx:delimitedField name="DE5249"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='MOA'">
          <sx:flatRecordType name='MOA'>
            <sx:delimitedField name="segmentType"/>
            <sx:nonrepeatingGroup name="C516">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C516">
                <sx:delimitedField name="DE5025"/>
                <sx:delimitedField name="DE5004"/>
                <sx:delimitedField name="DE6345"/>
                <sx:delimitedField name="DE6343"/>
                <sx:delimitedField name="DE4405"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='ALC'">
          <sx:flatRecordType name='ALC'>
            <sx:fieldDelimiter value="+" escapeCharacter="?"/>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE5463"/>
            <sx:nonrepeatingGroup name="C552">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C552">
                <sx:delimitedField name="DE1230"/>
                <sx:delimitedField name="DE5189"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE4471"/>
            <sx:delimitedField name="DE1227"/>
            <sx:nonrepeatingGroup name="C214">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C214">
                <sx:delimitedField name="DE7161"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
                <sx:delimitedField name="DE7160-1"/>
                <sx:delimitedField name="DE7160-2"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <!-- Detail segments -->
        <sx:when test="segmentType='LIN'">
          <sx:flatRecordType name='LIN'>
            <sx:fieldDelimiter value="+" escapeCharacter="?"/>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE1082"/>
            <sx:delimitedField name="DE1229"/>
            <sx:nonrepeatingGroup name="C212">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C212">
                <sx:delimitedField name="DE7140"/>
                <sx:delimitedField name="DE7143"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:nonrepeatingGroup name="C829">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C829">
                <sx:delimitedField name="DE5495"/>
                <sx:delimitedField name="DE1082"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE1222"/>
            <sx:delimitedField name="DE7083"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='PIA'">
          <sx:flatRecordType name='PIA'>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE4347"/>
            <sx:nonrepeatingGroup name="C212">
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <!--<sx:segmentDelimiter value="+" escapeCharacter="?"/>-->
              <sx:flatRecordType name="C212">
                <sx:delimitedField name="DE7140"/>
                <sx:delimitedField name="DE7143"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='IMD'">
          <sx:flatRecordType name='IMD'>
            <sx:fieldDelimiter value="+" escapeCharacter="?"/>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE7077"/>
            <sx:delimitedField name="DE7081"/>
            <sx:nonrepeatingGroup name="C273">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C273">
                <sx:delimitedField name="DE7009"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
                <sx:delimitedField name="DE7008-1"/>
                <sx:delimitedField name="DE7008-2"/>
                <sx:delimitedField name="DE3435"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE7383"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='QTY'">
          <sx:flatRecordType name='QTY'>
            <sx:delimitedField name="segmentType"/>
            <sx:nonrepeatingGroup name="C186">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C186">
                <sx:delimitedField name="DE6063"/>
                <sx:delimitedField name="DE6060"/>
                <sx:delimitedField name="DE6411"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='PRI'">
          <sx:flatRecordType name='PRI'>
            <sx:delimitedField name="segmentType"/>
            <sx:nonrepeatingGroup name="C509">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C509">
                <sx:delimitedField name="DE5125"/>
                <sx:delimitedField name="DE5118"/>
                <sx:delimitedField name="DE5375"/>
                <sx:delimitedField name="DE5387"/>
                <sx:delimitedField name="DE5284"/>
                <sx:delimitedField name="DE6411"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE5213"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='TAX'">
          <sx:flatRecordType name='TAX'>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE5283"/>
            <sx:nonrepeatingGroup name="C241">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C241">
                <sx:delimitedField name="DE5153"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
                <sx:delimitedField name="DE5152"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:nonrepeatingGroup name="C533">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C533">
                <sx:delimitedField name="DE5289"/>
                <sx:delimitedField name="DE1131"/>
                <sx:delimitedField name="DE3055"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE5286"/>
            <sx:nonrepeatingGroup name="C243">
              <sx:segmentDelimiter value="+" escapeCharacter="?"/>
              <sx:fieldDelimiter value=":" escapeCharacter="?"/>
              <sx:flatRecordType name="C243">
                <sx:delimitedField name="DE5279"/>
                <sx:delimitedField name="DE1131-1"/>
                <sx:delimitedField name="DE3055-1"/>
                <sx:delimitedField name="DE5278"/>
                <sx:delimitedField name="DE5273"/>
                <sx:delimitedField name="DE1131-2"/>
                <sx:delimitedField name="DE3055-2"/>
              </sx:flatRecordType>
            </sx:nonrepeatingGroup>
            <sx:delimitedField name="DE5305"/>
            <sx:delimitedField name="DE3446"/>
          </sx:flatRecordType>
        </sx:when>
		
        <!-- Trailer segments -->
        <sx:when test="segmentType='UNS'">
          <sx:flatRecordType name='UNS'>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE0081"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='UNT'">
          <sx:flatRecordType name='UNT'>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="DE0074"/>
            <sx:delimitedField name="DE0062"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="segmentType='UNZ'">
          <sx:flatRecordType name='UNZ'>
            <sx:fieldDelimiter value="+" escapeCharacter="?"/>
            <sx:delimitedField name="segmentType"/>
            <sx:delimitedField name="F0036"/>
            <sx:delimitedField name="F0020"/>
          </sx:flatRecordType>
        </sx:when>

        <sx:otherwise>
          <sx:flatRecordType name='ERROR'>
            <sx:delimitedField name="segmentType"/>
          </sx:flatRecordType>
        </sx:otherwise>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

</sx:resources>]]></programlisting>
      </figure>
      <para>
Note the following points about this script.
        <itemizedlist>
          <listitem>
            <para>
Record delimiters delimit the boundaries of a record, segment delimiters delimit
areas within a record, and repeat delimiters separate subrecords from each other
within segments. An <link xlink:href="../guide/index.html#sx:repeatingGroup">sx:repeatingGroup</link> reads the subrecords separated by repeat
delimiters within a segment. A special case is when there are a number of
segments, but at most one subrecord per segment, a nonrepeating group. An 
<link xlink:href="../guide/index.html#sx:nonrepeatingGroup">sx:nonrepeatingGroup</link> reads the single subrecord, if any.
              </para>
          </listitem><listitem><para>The continuation sequence for a linefeed 
                       is defined be the linefeed itself, e.g.
                               </para>
<programlisting><![CDATA[
    <sx:recordDelimiter value="\r\n" continuationSequence="\r\n"/>
    <sx:recordDelimiter value="\n" continuationSequence="\n"/>
]]></programlisting><para>This has the effect of stripping out the linefeed 
                      characters.
          </para>
                     </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-invoic96A.xml -i data/invoic96A.txt 
    -o output/invoic96A.xml invoic96A-to-xml
    ]]>
        </programlisting>
      </para>
    </section>
  </section>
  <section>
    <title>FpML Examples</title>
    <section>
      <title>FRA to FpML</title>
      <titleabbrev>FRA</titleabbrev>
      <indexterm>
        <primary>FpML</primary>
        <secondary>FRA</secondary>
      </indexterm>
      <para> Suppose "Bank A" has the following CSV file of FRA trades.  Each FRA
trade is represented by one record in the file.
      </para>
      <figure id="fra.csv" xreflabel="fra.csv flat file">
        <title>Input flat file fra.csv</title>
        <programlisting>
          <![CDATA[
product,trade_id,client_id,client_name,trade_date,buy_sell_code,currency,index,tenor,day_count_basis,fixed_rate,start_date,maturity_date,payment_date,notional
FRA,1001,party1,Party 1,2006/12/07,BUY,CAD,BA,3M,ACT/365,0.04,   2008/09/08,2008/12/08,2008/09/08,250000000
FRA,1002,party1,Party 1,2007/03/19,B,CAD,BA,3M,ACT/365,0.04,   2008/09/15,2008/12/15,2008/09/15,110000000
FRA,1003,party1,Party 1,2007/03/19,SELL,CAD,BA,3M,ACT/365,0.04,  2008/12/15,2009/03/16,2008/12/15,70000000 
FRA,1004,party2,Party 2,2007/05/02,BUY,USD,LIBOR,3M,ACT/360,0.04,2009/02/02,2009/05/04,2009/02/02,100000000
FRA,1005,party2,Party 2,2007/05/02,BUY,USD,LIBOR,3M,ACT/360,0.04,2009/02/02,2009/05/04,2009/02/02,100000000
FRA,1006,party3,Party 3,2007/08/01,B,USD,LIBOR,3M,ACT/360,0.05,09/05/01,2009/08/04,2009/05/01,50000000 
]]>
        </programlisting>
      </figure>
      <para>
    Note that two of the FRA trades have errors.  The trade with trade_id 1002
    has an invalid buy_sell_code, "B" instead of "BUY".  The trade with trade id
    1006 has the same problem with the buy_sell_code, and also has an invalid
    start_date, with a two digit year instead of a four digit year.  Bank A
    wants to reject the trades with errors and write them along with an error
    message to a discard file.
      </para>
      <para>Bank A wants the XML output to look as follows.
      </para>
      <figure id="fra.xml">
        <title>Output XML file fra.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<dataDocument xmlns="http://www.fpml.org/FpML-5-0/reporting" 
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" fpmlVersion="5-0" 
              xsi:schemaLocation="http://www.fpml.org/FpML-5-0/reporting ../fpml-main-5-0.xsd">
  <trade>
    <tradeHeader>
      <partyTradeIdentifier>
        <tradeId tradeIdScheme="http://www.banka.com/ird/trade-id">1001</tradeId>
      </partyTradeIdentifier>
      <tradeDate>2006-12-07</tradeDate>
    </tradeHeader>
    <fra>
      <sellerPartyReference>party1</sellerPartyReference>
      <adjustedEffectiveDate>2008-09-08</adjustedEffectiveDate>
      <adjustedTerminationDate>2008-12-08</adjustedTerminationDate>
      <paymentDate>
        <adjustedDate>2008-09-08</adjustedDate>
      </paymentDate>
      <dayCountFraction>ACT/365</dayCountFraction>
      <notional>
        <currency>CAD</currency>
        <amount>250000000</amount>
      </notional>
      <fixedRate>0.04</fixedRate>
      <floatingRateIndex>BA</floatingRateIndex>
      <indexTenor>
        <periodMultiplier>3</periodMultiplier>
        <period>M</period>
      </indexTenor>
    </fra>
  </trade>
  <trade>
    <tradeHeader>
      <partyTradeIdentifier>
        <tradeId tradeIdScheme="http://www.banka.com/ird/trade-id">1003</tradeId>
      </partyTradeIdentifier>
      <tradeDate>2007-03-19</tradeDate>
    </tradeHeader>
    <fra>
      <buyerPartyReference>party1</buyerPartyReference>
      <adjustedEffectiveDate>2008-12-15</adjustedEffectiveDate>
      <adjustedTerminationDate>2009-03-16</adjustedTerminationDate>
      <paymentDate>
        <adjustedDate>2008-12-15</adjustedDate>
      </paymentDate>
      <dayCountFraction>ACT/365</dayCountFraction>
      <notional>
        <currency>CAD</currency>
        <amount>70000000</amount>
      </notional>
      <fixedRate>0.04</fixedRate>
      <floatingRateIndex>BA</floatingRateIndex>
      <indexTenor>
        <periodMultiplier>3</periodMultiplier>
        <period>M</period>
      </indexTenor>
    </fra>
  </trade>
  <trade>
    <tradeHeader>
      <partyTradeIdentifier>
        <tradeId tradeIdScheme="http://www.banka.com/ird/trade-id">1004</tradeId>
      </partyTradeIdentifier>
      <tradeDate>2007-05-02</tradeDate>
    </tradeHeader>
    <fra>
      <sellerPartyReference>party2</sellerPartyReference>
      <adjustedEffectiveDate>2009-02-02</adjustedEffectiveDate>
      <adjustedTerminationDate>2009-05-04</adjustedTerminationDate>
      <paymentDate>
        <adjustedDate>2009-02-02</adjustedDate>
      </paymentDate>
      <dayCountFraction>ACT/360</dayCountFraction>
      <notional>
        <currency>USD</currency>
        <amount>100000000</amount>
      </notional>
      <fixedRate>0.04</fixedRate>
      <floatingRateIndex>LIBOR</floatingRateIndex>
      <indexTenor>
        <periodMultiplier>3</periodMultiplier>
        <period>M</period>
      </indexTenor>
    </fra>
  </trade>
  <trade>
    <tradeHeader>
      <partyTradeIdentifier>
        <tradeId tradeIdScheme="http://www.banka.com/ird/trade-id">1005</tradeId>
      </partyTradeIdentifier>
      <tradeDate>2007-05-02</tradeDate>
    </tradeHeader>
    <fra>
      <sellerPartyReference>party2</sellerPartyReference>
      <adjustedEffectiveDate>2009-02-02</adjustedEffectiveDate>
      <adjustedTerminationDate>2009-05-04</adjustedTerminationDate>
      <paymentDate>
        <adjustedDate>2009-02-02</adjustedDate>
      </paymentDate>
      <dayCountFraction>ACT/360</dayCountFraction>
      <notional>
        <currency>USD</currency>
        <amount>100000000</amount>
      </notional>
      <fixedRate>0.04</fixedRate>
      <floatingRateIndex>LIBOR</floatingRateIndex>
      <indexTenor>
        <periodMultiplier>3</periodMultiplier>
        <period>M</period>
      </indexTenor>
    </fra>
  </trade>
  <party id="bankA">
    <partyId>Bank A</partyId>
  </party>
  <party id="party1">
    <partyId>Party 1</partyId>
  </party>
  <party id="party3">
    <partyId>Party 3</partyId>
  </party>
  <party id="party2">
    <partyId>Party 2</partyId>
  </party>
</dataDocument>
]]>
        </programlisting>
      </figure>
      <para>
  Note that the document concludes with a unique list of parties that
  are referenced by
        <sgmltag>id</sgmltag>
in the
        <sgmltag>buyerPartyReference</sgmltag>
and
        <sgmltag>sellerPartyReference</sgmltag>
  elements.
      </para>
      <para>The required resources script is
      </para>
      <figure id="resources-fra.xml">
        <title>Resources script resources-fra.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:fn="http://www.w3.org/2005/xpath-functions">

  <sx:service id="fra-to-xml">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="fra-xml"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="fra-xml">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile ref="fra-flat-file"/>
      </sx:flatFileReader>
      <sx:recordValidator message="Error in trade {trade_id}.">
        <sx:fieldValidator field="buy_sell_code"
                          message="Invalid buy_sell_code {buy_sell_code}.">
          <sx:or>
            <sx:valueRestriction pattern="BUY"/>
            <sx:valueRestriction pattern="SELL"/>
          </sx:or>
        </sx:fieldValidator>
        <sx:fieldValidator field="start_date"
                           message="Invalid start_date {start_date}.">
          <sx:valueRestriction pattern="(19|20)\d\d[/](0[1-9]|1[012])[/](0[1-9]|[12][0-9]|3[01])"/>
        </sx:fieldValidator>
        <sx:fieldValidator field="maturity_date"
                           message="Invalid maturity_date {maturity_date}.">
          <sx:valueRestriction pattern="(20|21)\d\d[/](0[1-9]|1[012])[/](0[1-9]|[12][0-9]|3[01])"/>
        </sx:fieldValidator>
      </sx:recordValidator>
      <sx:discardHandler>
        <sx:log message="{$sx:message}"/>
        <sx:modifyRecord>
          <sx:newField name="message" value="{$sx:message}"/>
        </sx:modifyRecord>
        <sx:flatFileWriter>
          <sx:fileSink file="output/fra-error.csv"/>
        </sx:flatFileWriter>
      </sx:discardHandler>
    </sx:recordStream>
    <sx:recordMapping ref="fra-to-xml-mapping"/>
  </sx:recordContent>

  <sx:flatFile id="fra-flat-file">
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:fieldDelimiter value=","/>
        <sx:delimitedField name="record_type"/>
        <sx:when test="record_type='FRA'">
          <sx:flatRecordType name='fra'>
            <sx:fieldDelimiter value=","/>
            <sx:delimitedField name="record_type"/>
            <sx:delimitedField name="trade_id"/>
            <sx:delimitedField name="client_id"/>
            <sx:delimitedField name="client_name"/>
            <sx:delimitedField name="trade_date"/>
            <sx:delimitedField name="buy_sell_code"/>
            <sx:delimitedField name="currency"/>
            <sx:delimitedField name="index"/>
            <sx:delimitedField name="tenor"/>
            <sx:delimitedField name="day_count_basis"/>
            <sx:delimitedField name="fixed_rate"/>
            <sx:delimitedField name="start_date"/>
            <sx:delimitedField name="maturity_date"/>
            <sx:delimitedField name="payment_date"/>
            <sx:delimitedField name="notional"/>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="fra-to-xml-mapping">
    <dataDocument xmlns="http://www.fpml.org/FpML-5-0/reporting"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  fpmlVersion="5-0"
                  xsi:schemaLocation="http://www.fpml.org/FpML-5-0/reporting ../fpml-main-5-0.xsd">
      <sx:groupBy fields="trade_id">
        <trade>
          <tradeHeader>
            <partyTradeIdentifier>
              <sx:fieldElementMap field="trade_id"
                                  element="tradeId">
                <sx:fieldAttributeMap value="http://www.banka.com/ird/trade-id"
                                      attribute="tradeIdScheme"/>
              </sx:fieldElementMap>
            </partyTradeIdentifier>
            <tradeDate>
              <sx:toXmlDate fromFormat="yyyy/MM/dd">
                <sx:toString value="{trade_date}"/>
              </sx:toXmlDate>
            </tradeDate>
          </tradeHeader>
          <sx:onRecord recordType="fra">
            <fra>
              <sx:choose>
                <sx:when test="buy_sell_code='BUY'">
                  <sx:fieldElementMap field="client_id"
                                      element="sellerPartyReference"/>
                </sx:when>
                <sx:otherwise>
                  <sx:fieldElementMap field="client_id"
                                      element="buyerPartyReference"/>
                </sx:otherwise>
              </sx:choose>
              <adjustedEffectiveDate>
                <sx:toXmlDate fromFormat="yyyy/MM/dd">
                  <sx:toString value="{start_date}"/>
                </sx:toXmlDate>
              </adjustedEffectiveDate>
              <adjustedTerminationDate>
                <sx:toXmlDate fromFormat="yyyy/MM/dd">
                  <sx:toString value="{maturity_date}"/>
                </sx:toXmlDate>
              </adjustedTerminationDate>
              <paymentDate>
                <adjustedDate>
                  <sx:toXmlDate fromFormat="yyyy/MM/dd">
                    <sx:toString value="{payment_date}"/>
                  </sx:toXmlDate>
                </adjustedDate>
              </paymentDate>
              <sx:fieldElementMap field="day_count_basis"
                                  element="dayCountFraction"/>
              <notional>
                <sx:fieldElementMap field="currency"
                                    element="currency"/>
                <sx:fieldElementMap field="notional"
                                    element="amount"/>
              </notional>
              <sx:fieldElementMap field="fixed_rate"
                                  element="fixedRate"/>
              <sx:fieldElementMap field="index"
                                  element="floatingRateIndex"/>
              <indexTenor>
                <sx:choose>
                  <sx:when test="fn:ends-with(tenor,'D')">
                    <sx:fieldElementMap element="periodMultiplier">
                      <sx:toString select="fn:substring-before(tenor,'D')"/>
                    </sx:fieldElementMap>
                    <period>D</period>
                  </sx:when>
                  <sx:when test="fn:ends-with(tenor,'M')">
                    <sx:fieldElementMap element="periodMultiplier">
                      <sx:toString select="fn:substring-before(tenor,'M')"/>
                    </sx:fieldElementMap>
                    <period>M</period>
                  </sx:when>
                  <sx:when test="fn:ends-with(tenor,'Y')">
                    <sx:fieldElementMap element="periodMultiplier">
                      <sx:toString select="fn:substring-before(tenor,'Y')"/>
                    </sx:fieldElementMap>
                    <period>Y</period>
                  </sx:when>
                </sx:choose>
              </indexTenor>
            </fra>
          </sx:onRecord>
        </trade>
      </sx:groupBy>

      <sx:nestedContent>
        <sx:recordContent ref="clients"/>
      </sx:nestedContent>
    </dataDocument>
  </sx:recordMapping>

  <sx:recordContent id="clients">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile ref="fra-flat-file"/>
      </sx:flatFileReader>
      <sx:recordProjection fields="client_id client_name"/>
    </sx:recordStream>
    <sx:recordMapping>
      <party id="bankA">
        <partyId>Bank A</partyId>
      </party>
      <sx:onRecord>
        <party>
          <sx:fieldAttributeMap field="client_id" attribute="id"/>
          <sx:fieldElementMap field="client_name" element="partyId"/>
        </party>
      </sx:onRecord>
    </sx:recordMapping>
  </sx:recordContent>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
  We use the
        <link xlink:href="../guide/index.html#sx:nestedContent">sx:nestedContent</link>
  element to insert a list of parties from the
        <filename>swap.csv</filename>
file into the output XML, and we use the
        <link xlink:href="../guide/index.html#sx:recordProjection">sx:recordProjection</link>
  element to eliminate duplicate pairs of client_id and client_name.
      </para>
      <para>
You can run this example on the command line by entering
      </para>
      <programlisting>
        <![CDATA[
servingxml -i data/fra.csv -o output/fra.xml -r resources-fra.xml fra-to-xml
]]>
      </programlisting>
      <para>
  The following error messages will be written to the console (or log file.)
        <programlisting>
25-Sep-2008 10:10:47 PM com.servingxml.util.system.DefaultLogger error
SEVERE: Error in record "fra" on line 3.  Error in trade 1002. Invalid buy_sell_code B.
25-Sep-2008 10:10:47 PM com.servingxml.util.system.DefaultLogger error
SEVERE: Error in record "fra" on line 7.  Error in trade 1006. Invalid buy_sell_code B. Invalid start_date 09/05/01.
        </programlisting>
      </para>
    </section>
    <section>
      <title>Swap to FpML</title>
      <titleabbrev>Swap</titleabbrev>
      <indexterm>
        <primary>FpML</primary>
        <secondary>Swap</secondary>
      </indexterm>
      <para> Suppose "Bank A" has the following CSV file of SWAP trades.  Each swap
trade is represented by two records in the file, one for the pay (PAY) side, and
one for the receive (REC) side.
      </para>
      <figure id="swap.csv" xreflabel="swap.csv flat file">
        <title>Input flat file swap.csv</title>
        <programlisting>
          <![CDATA[
product,trade_id,client_id,client_name,trade_date,pay_receive_code,currency,index,tenor,day_count_basis,fixed_rate,start_date,maturity_date,reset_date,payment_date,notional,calculation_period
SWAP,2001,party1,Party 1,2008/05/14,PAY,FIXED,CAD,BA,6M,30/360,0.04,2008/07/17,2009/01/17,2008/07/17,2009/01/17,10000000.00,6M
SWAP,2001,party1,Party 1,2008/05/14,REC,FLOAT,CAD,BA,6M,30/360,0.04,2008/07/17,2009/01/17,2008/07/17,2009/01/17,10000000.00,6M
SWAP,2002,party2,Party 2,2008/05/14,PAY,FIXED,CAD,BA,6M,30/360,0.04,2008/07/17,2009/01/17,2008/07/17,2009/01/17,10000000.00,6M
SWAP,2002,party2,Party 2,2008/05/14,R,FLOAT,CAD,BA,6M,30/360,0.04,2008/07/17,2009/01/17,2008/07/17,2009/01/17,10000000.00,6M
]]>
        </programlisting>
      </figure>
      <para>
    Note that one of the records, the receive side for the trade with trade_id
    2002, has an invalid value for pay_receive_code, the value has been
    mistakenly entered as "R" instead of "REC".  Bank A wants to validate this
    field, and if it is wrong for either side of the swap, Bank A wants to
    reject both sides, and write them both with an error message to a discard
    file.
      </para>
      <para>Bank A wants the XML output to look as follows.
      </para>
      <figure id="swap.xml">
        <title>Output XML file swap.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<dataDocument xmlns="http://www.fpml.org/FpML-5-0/reporting" 
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
              fpmlVersion="5-0" 
              xsi:schemaLocation="http://www.fpml.org/FpML-5-0/reporting ../fpml-main-5-0.xsd">
  <trade>
    <tradeHeader>
      <partyTradeIdentifier>
        <tradeId tradeIdScheme="http://www.banka.com/ird/trade-id">2001</tradeId>
      </partyTradeIdentifier>
      <tradeDate>2008-05-14</tradeDate>
    </tradeHeader>
    <swap>
      <swapStream>
        <payerPartyReference href="bankA"/>
        <calculationPeriodDates id="floatingCalcPeriodDates">
          <effectiveDate>
            <adjustedDate>2008-07-17</adjustedDate>
          </effectiveDate>
          <terminationDate>
            <adjustedDate>2009-01-17</adjustedDate>
          </terminationDate>
          <calculationPeriodFrequency>
            <periodMultiplier>6</periodMultiplier>
            <period>M</period>
          </calculationPeriodFrequency>
        </calculationPeriodDates>
        <calculationPeriodAmount>
          <calculation>
            <notionalSchedule>
              <notionalStepSchedule>
                <initialValue>10000000.00</initialValue>
                <currency currencyScheme="http://www.fpml.org/ext/iso4217">CAD</currency>
              </notionalStepSchedule>
            </notionalSchedule>
            <fixedRateSchedule>
              <initialValue>0.04</initialValue>
            </fixedRateSchedule>
            <dayCountFraction>30/360</dayCountFraction>
          </calculation>
        </calculationPeriodAmount>
      </swapStream>
      <swapStream>
        <payerPartyReference href="party1"/>
        <calculationPeriodDates id="floatingCalcPeriodDates">
          <effectiveDate>
            <adjustedDate>2008-07-17</adjustedDate>
          </effectiveDate>
          <terminationDate>
            <adjustedDate>2009-01-17</adjustedDate>
          </terminationDate>
          <calculationPeriodFrequency>
            <periodMultiplier>6</periodMultiplier>
            <period>M</period>
          </calculationPeriodFrequency>
        </calculationPeriodDates>
        <calculationPeriodAmount>
          <calculation>
            <notionalSchedule>
              <notionalStepSchedule>
                <initialValue>10000000.00</initialValue>
                <currency currencyScheme="http://www.fpml.org/ext/iso4217">CAD</currency>
              </notionalStepSchedule>
            </notionalSchedule>
            <floatingRateCalculation>
              <floatingRateIndex>BA</floatingRateIndex>
              <indexTenor>
                <periodMultiplier>6</periodMultiplier>
                <period>M</period>
              </indexTenor>
            </floatingRateCalculation>
            <dayCountFraction>30/360</dayCountFraction>
          </calculation>
        </calculationPeriodAmount>
      </swapStream>
    </swap>
  </trade>
  <party id="bankA">
    <partyId>Bank A</partyId>
  </party>
  <party id="party1">
    <partyId>Party 1</partyId>
  </party>
  <party id="party2">
    <partyId>Party 2</partyId>
  </party>
</dataDocument>
]]>
        </programlisting>
      </figure>
      <para>
    Note that the document concludes with a unique list of parties that
    are referenced by
        <sgmltag>id</sgmltag>
in the
        <sgmltag>payerPartyReference</sgmltag>
elements.
      </para>
      <para>The required resources script is
      </para>
      <figure id="resources-swap.xml">
        <title>Resources script resources-swap.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:fn="http://www.w3.org/2005/xpath-functions">

  <sx:service id="swap-to-xml">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="swap-xml"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="swap-xml">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile ref="swap-flat-file"/>
      </sx:flatFileReader>
      <sx:modifyRecord>
        <sx:newField name="trade_id" select="legs/child::node()[1]/trade_id"/>
        <sx:newField name="trade_date" select="legs/child::node()[1]/trade_date"/>
      </sx:modifyRecord>
      <sx:recordValidator ref="swap-validator"/>
      <sx:discardHandler>
        <sx:log message="{$sx:message}"/>
        <sx:splitRecord recordType="swap" repeatingGroup="legs"/>
        <sx:flatFileWriter>
          <sx:fileSink file="output/swap-error.csv"/>
        </sx:flatFileWriter>
      </sx:discardHandler>
    </sx:recordStream>
    <sx:recordMapping ref="swap-to-xml-mapping"/>
  </sx:recordContent>

  <sx:flatFile id="swap-flat-file">
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:compositeFlatRecordType>
        <sx:delimitedField name="record_type"/>
        <sx:delimitedField name="trade_id"/>
        <sx:combinePhysicalRecords recordType="swap"
                              repeatingGroup="legs"
                              endTest="sx:current//trade_id != sx:previous//trade_id">
          <sx:flatRecordTypeChoice>
            <sx:fieldDelimiter value=","/>
            <sx:delimitedField name="record_type"/>
            <sx:delimitedField name="trade_id"/>
            <sx:delimitedField name="client_id"/>
            <sx:delimitedField name="client_name"/>
            <sx:delimitedField name="trade_date"/>
            <sx:delimitedField name="pay_receive_code"/>
            <sx:delimitedField name="fixed_float_code"/>
            <sx:when test="record_type='SWAP' and fixed_float_code='FLOAT'">
              <sx:flatRecordType name='swap_floating_leg'>
                <sx:fieldDelimiter value=","/>
                <sx:delimitedField name="record_type"/>
                <sx:delimitedField name="trade_id"/>
                <sx:delimitedField name="client_id"/>
                <sx:delimitedField name="client_name"/>
                <sx:delimitedField name="trade_date"/>
                <sx:delimitedField name="pay_receive_code"/>
                <sx:delimitedField name="fixed_float_code"/>
                <sx:delimitedField name="currency"/>
                <sx:delimitedField name="index"/>
                <sx:delimitedField name="tenor"/>
                <sx:delimitedField name="day_count_basis"/>
                <sx:delimitedField name="fixed_rate"/>
                <sx:delimitedField name="start_date"/>
                <sx:delimitedField name="maturity_date"/>
                <sx:delimitedField name="reset_date"/>
                <sx:delimitedField name="payment_date"/>
                <sx:delimitedField name="notional"/>
                <sx:delimitedField name="calculation_period"/>
              </sx:flatRecordType>
            </sx:when>
            <sx:when test="record_type='SWAP' and fixed_float_code='FIXED'">
              <sx:flatRecordType name='swap_fixed_leg'>
                <sx:fieldDelimiter value=","/>
                <sx:delimitedField name="record_type"/>
                <sx:delimitedField name="trade_id"/>
                <sx:delimitedField name="client_id"/>
                <sx:delimitedField name="client_name"/>
                <sx:delimitedField name="trade_date"/>
                <sx:delimitedField name="pay_receive_code"/>
                <sx:delimitedField name="fixed_float_code"/>
                <sx:delimitedField name="currency"/>
                <sx:delimitedField name="index"/>
                <sx:delimitedField name="tenor"/>
                <sx:delimitedField name="day_count_basis"/>
                <sx:delimitedField name="fixed_rate"/>
                <sx:delimitedField name="start_date"/>
                <sx:delimitedField name="maturity_date"/>
                <sx:delimitedField name="reset_date"/>
                <sx:delimitedField name="payment_date"/>
                <sx:delimitedField name="notional"/>
                <sx:delimitedField name="calculation_period"/>
              </sx:flatRecordType>
            </sx:when>
          </sx:flatRecordTypeChoice>
        </sx:combinePhysicalRecords>
      </sx:compositeFlatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>
  <sx:recordValidator id="swap-validator"
                      recordType="swap"
                      message="Error in trade {trade_id}.">
    <sx:fieldValidator field="legs"
                       message="">
      <sx:recordValidator>
        <sx:fieldValidator field="pay_receive_code"
                           message="Invalid pay_receive_code {pay_receive_code}.">
          <sx:or>
            <sx:valueRestriction pattern="PAY"/>
            <sx:valueRestriction pattern="REC"/>
          </sx:or>
        </sx:fieldValidator>
        <sx:fieldValidator field="fixed_float_code"
                           message="Invalid fixed_float_code {fixed_float_code}.">
          <sx:or>
            <sx:valueRestriction pattern="FIXED"/>
            <sx:valueRestriction pattern="FLOAT"/>
          </sx:or>
        </sx:fieldValidator>
        <sx:fieldValidator field="start_date"
                           message="Invalid start_date {start_date}.">
          <sx:valueRestriction pattern="(19|20)\d\d[/](0[1-9]|1[012])[/](0[1-9]|[12][0-9]|3[01])"/>
        </sx:fieldValidator>
        <sx:fieldValidator field="maturity_date"
                           message="Invalid maturity_date {maturity_date}.">
          <sx:valueRestriction pattern="(20|21)\d\d[/](0[1-9]|1[012])[/](0[1-9]|[12][0-9]|3[01])"/>
        </sx:fieldValidator>
      </sx:recordValidator>
    </sx:fieldValidator>
  </sx:recordValidator>

  <sx:recordMapping id="swap-to-xml-mapping">
    <dataDocument xmlns="http://www.fpml.org/FpML-5-0/reporting"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  fpmlVersion="5-0"
                  xsi:schemaLocation="http://www.fpml.org/FpML-5-0/reporting ../fpml-main-5-0.xsd">
      <sx:groupBy fields="trade_id">
        <trade>
          <tradeHeader>
            <partyTradeIdentifier>
              <sx:fieldElementMap field="trade_id" element="tradeId">
                <sx:fieldAttributeMap value="http://www.banka.com/ird/trade-id"
                                      attribute="tradeIdScheme"/>
              </sx:fieldElementMap>
            </partyTradeIdentifier>
            <tradeDate>
              <sx:toXmlDate fromFormat="yyyy/MM/dd">
                <sx:toString value="{trade_date}"/>
              </sx:toXmlDate>
            </tradeDate>
          </tradeHeader>
          <swap>
            <sx:subrecordMapping repeatingGroup="legs">
              <sx:groupBy fields="trade_id pay_receive_code">
                <swapStream>
                  <sx:choose>
                    <sx:when test="pay_receive_code='PAY'">
                      <payerPartyReference>
                        <sx:fieldAttributeMap value="bankA"
                                              attribute="href"/>
                      </payerPartyReference>
                    </sx:when>
                    <sx:when test="pay_receive_code='REC'">
                      <payerPartyReference>
                        <sx:fieldAttributeMap field="client_id"
                                              attribute="href"/>
                      </payerPartyReference>
                    </sx:when>
                  </sx:choose>
                  <calculationPeriodDates id="floatingCalcPeriodDates">
                    <effectiveDate>
                      <adjustedDate>
                        <sx:toXmlDate fromFormat="yyyy/MM/dd">
                          <sx:toString value="{start_date}"/>
                        </sx:toXmlDate>
                      </adjustedDate>
                    </effectiveDate>
                    <terminationDate>
                      <adjustedDate>
                        <sx:toXmlDate fromFormat="yyyy/MM/dd">
                          <sx:toString value="{maturity_date}"/>
                        </sx:toXmlDate>
                      </adjustedDate>
                    </terminationDate>
                    <calculationPeriodFrequency>
                      <sx:parameter name="term" value="{calculation_period}"/>
                      <sx:choose ref="expand-term"/>
                    </calculationPeriodFrequency>
                  </calculationPeriodDates>
                  <calculationPeriodAmount>
                    <calculation>
                      <notionalSchedule>
                        <notionalStepSchedule>
                          <sx:fieldElementMap field="notional" element="initialValue"/>
                          <sx:fieldElementMap field="currency" element="currency">
                            <sx:fieldAttributeMap value="http://www.fpml.org/ext/iso4217"
                                                  attribute="currencyScheme"/>
                          </sx:fieldElementMap>
                        </notionalStepSchedule>
                      </notionalSchedule>
                      <sx:choose>
                        <sx:when test="fixed_float_code='FLOAT'">
                          <floatingRateCalculation>
                            <sx:fieldElementMap field="index"
                                                element="floatingRateIndex"/>
                            <indexTenor>
                              <sx:parameter name="term" value="{tenor}"/>
                              <sx:choose ref="expand-term"/>
                            </indexTenor>
                          </floatingRateCalculation>
                        </sx:when>
                        <sx:when test="fixed_float_code='FIXED'">
                          <fixedRateSchedule>
                            <sx:fieldElementMap field="fixed_rate"
                                                element="initialValue"/>
                          </fixedRateSchedule>
                        </sx:when>
                      </sx:choose>
                      <sx:fieldElementMap field="day_count_basis"
                                          element="dayCountFraction"/>
                    </calculation>
                  </calculationPeriodAmount>
                </swapStream>
              </sx:groupBy>
            </sx:subrecordMapping>
          </swap>
        </trade>
      </sx:groupBy>

      <sx:nestedContent>
        <sx:recordContent ref="clients"/>
      </sx:nestedContent>
    </dataDocument>
  </sx:recordMapping>

  <!-- Expands a parameter named "term" with a value <number><D|M|Y> as
    <periodMultiplier>number</periodMultiplier>
    <period>D|M|Y</period>
  -->
  <sx:choose id="expand-term">
    <sx:when test="fn:ends-with($term,'D')">
      <sx:fieldElementMap element="periodMultiplier">
        <sx:toString select="fn:substring-before($term,'D')"/>
      </sx:fieldElementMap>
      <period>D</period>
    </sx:when>
    <sx:when test="fn:ends-with($term,'M')">
      <sx:fieldElementMap element="periodMultiplier">
        <sx:toString select="fn:substring-before($term,'M')"/>
      </sx:fieldElementMap>
      <period>M</period>
    </sx:when>
    <sx:when test="fn:ends-with($term,'Y')">
      <sx:fieldElementMap element="periodMultiplier">
        <sx:toString select="fn:substring-before($term,'Y')"/>
      </sx:fieldElementMap>
      <period>Y</period>
    </sx:when>
  </sx:choose>

  <sx:recordContent id="clients">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile>
          <sx:flatFileHeader lineCount="1"/>
          <sx:flatFileBody>
            <sx:flatRecordType>
              <sx:fieldDelimiter value=","/>
              <sx:delimitedField name="record_type"/>
              <sx:delimitedField name="trade_id"/>
              <sx:delimitedField name="client_id"/>
              <sx:delimitedField name="client_name"/>
            </sx:flatRecordType>
          </sx:flatFileBody>
        </sx:flatFile>
      </sx:flatFileReader>
      <sx:recordProjection fields="client_id client_name"/>
    </sx:recordStream>
    <sx:recordMapping>
      <party id="bankA">
        <partyId>Bank A</partyId>
      </party>
      <sx:onRecord>
        <party>
          <sx:fieldAttributeMap field="client_id" attribute="id"/>
          <sx:fieldElementMap field="client_name" element="partyId"/>
        </party>
      </sx:onRecord>
    </sx:recordMapping>
  </sx:recordContent>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
    Note the following points about this script.
      </para>
      <itemizedlist>
        <listitem>
          <para>We use the
            <link xlink:href="../guide/index.html#sx:combineRecords">sx:combineRecords</link>
        element to compose a single record from the two legs of the swap.  This
        way, when we validate the composite record, a failure in either of the
        legs will result in the entire swap being discarded, not just one of the
        legs.
          </para>
        </listitem>
        <listitem>
          <para>
        We use the
            <link xlink:href="../guide/index.html#sx:nestedContent">sx:nestedContent</link>
        element to insert a list of parties from the
            <filename>swap.csv</filename>
file into the output XML, and we use the
            <link xlink:href="../guide/index.html#sx:recordProjection">sx:recordProjection</link>
        element to eliminate duplicate pairs of client_id and client_name.
          </para>
        </listitem>
        <listitem>
          <para>Inside the
            <link xlink:href="../guide/index.html#sx:discardHandler">sx:discardHandler</link>
        element, we use the
            <link xlink:href="../guide/index.html#sx:splitRecord">sx:splitRecord</link>
        element to decompose the composite swap record back into separate leg
        records.  This allows us to easily use the default record writer to
        write the legs to a discard file.
          </para>
        </listitem>
        <listitem>
          <para>We have two fields,
            <code>calculation_period</code>
and
            <code>tenor</code>
, that have values like
            <code>3M</code>
and
            <code>30D</code>
, where the numeric value and the trailing letter need to
       be mapped separately to the elements
            <sgmltag>periodMultiplier</sgmltag>
       and
            <sgmltag>period</sgmltag>
.  We use a parameterized
            <link xlink:href="../guide/index.html#sx:choose">sx:choose</link>
      instruction to handle both cases.
          </para>
        </listitem>
      </itemizedlist>
      <para>
You can run this example on the command line by entering
      </para>
      <programlisting>
        <![CDATA[
servingxml -i data/swap.csv -o output/swap.xml -r resources-swap.xml swap-to-xml
]]>
      </programlisting>
      <para>
  The following error message will be written to the console (or log file.)
        <programlisting>
25-Sep-2008 10:10:54 PM com.servingxml.util.system.DefaultLogger error
SEVERE: Error in record "swap" on line 5.  Error in trade 2002.  Invalid pay_receive_code R.</programlisting>
      </para>
    </section>
  </section>
  <section>
    <title>Fixed Width Fields, Single Record Type, Line Delimited</title>
    <section>
      <title>A flat file to XML mapping with field substitutions (abtest)</title>
      <titleabbrev>field substitutions</titleabbrev>
      <indexterm>
        <primary>field substitutions</primary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file to XML.
      </para>
      <para>
The input file is a positional file.
      </para>
      <figure id="abtest.txt" xreflabel="abtest.txt flat file">
        <title>Input flat file abtest.txt</title>
        <programlisting>
          <![CDATA[
ABTESTCD10 
ACTESTCD12 
ABTESTCC80
]]>
        </programlisting>
      </figure>
      <para>
The requirements are as follows:
        <itemizedlist>
          <listitem>
First 2 chars: if AB the output will be SOUTH, if AC then output is WEST.
          </listitem>
          <listitem>
For the 7th and 9th chars:  if CD, then output change to 01, otherwise 02
          </listitem>
        </itemizedlist>
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="recs.xml">
        <title>Output XML file Recs.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<Recs>
  <Rec>
    <First>SOUTH</First>
    <Second>TEST</Second>
    <Third>01</Third>
    <Last>10</Last>
  </Rec>
  <Rec>
    <First>WEST</First>
    <Second>TEST</Second>
    <Third>01</Third>
    <Last>12</Last>
  </Rec>
  <Rec>
    <First>SOUTH</First>
    <Second>TEST</Second>
    <Third>02</Third>
    <Last>80</Last>
  </Rec>
</Recs>]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-abtest.xml">
        <title>Resources script resources-abtest.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0"?>
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:msv="http://www.servingxml.com/extensions/msv">

  <sx:service id="abtest">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="data"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="data">
    <sx:flatFileReader>
      <sx:urlSource url="data/abtest.txt"/>
      <sx:flatFile ref="flatFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="abtestToXml"/>
  </sx:recordContent>

  <sx:flatFile id="flatFile">
    <sx:flatFileBody>
      <sx:flatRecordType name="match">
        <sx:positionalField name="first" width="2"/>
        <sx:positionalField name="second" width="4"/>
        <sx:positionalField name="third" width="2"/>
        <sx:positionalField name="fourth" width="2"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="abtestToXml">
    <Recs>
      <sx:onRecord>
        <Rec>
          <sx:fieldElementMap match="first[text()='AB']" select="'SOUTH'" element="First"/>
          <sx:fieldElementMap match="first[text()='AC']" select="'WEST'" element="First"/>
          <sx:fieldElementMap field="second" element="Second"/>
          <sx:fieldElementMap match="third[text()='CD']" select="'01'" element="Third"/>
          <sx:fieldElementMap match="third[text()!='CD']" select="'02'" element="Third"/>
          <sx:fieldElementMap field="fourth" element="Last"/>
        </Rec>
      </sx:onRecord>
    </Recs>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-abtest.xml -o output/abtest.xml abtest
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Mapping a record to separate top level sections in the XML (persons)</title>
      <titleabbrev>persons</titleabbrev>
      <para>
Suppose you have the following positional file of persons and their addresses.
      </para>
      <figure id="segments.txt" xreflabel="segments.txt flat file">
        <title>Input flat file persons.txt</title>
        <programlisting>
          <![CDATA[
PersonId Name       FirstName       Street              Postcode    CityTown
1        Jones      Joe             215 Walmer Rd       M5R3P7      Toronto
1        Jones      Joe             180 Redwood ST      94102-3280  San Francisco
2        Davis      Ken             212 Harbord St      M5S1H6      Toronto
3        Morris     Jane            1100 Danforth Ave   M4J1N2      Toronto
3        Morris     Jane            6 Green St          94111-1402  San Francisco
]]>
        </programlisting>
      </figure>
      <para>
Each line containes information about a person and an address.
A person may have multiple lines indicating multiple addresses.
      </para>
      <para>
You want the XML output to look as follows.
      </para>
      <figure id="persons.xml">
        <title>Output XML file persons.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<Persons-Addresses>
  <Persons>
    <Person>
      <PersonId>1</PersonId>
      <Name>Jones</Name>
      <FirstName>Joe</FirstName>
    </Person>
    <Person>
      <PersonId>2</PersonId>
      <Name>Davis</Name>
      <FirstName>Ken</FirstName>
    </Person>
    <Person>
      <PersonId>3</PersonId>
      <Name>Morris</Name>
      <FirstName>Jane</FirstName>
    </Person>
  </Persons>
  <Addresses>
    <Address>
      <PersonId>1</PersonId>
      <Street>215 Walmer Rd</Street>
      <PostCode>M5R3P7</PostCode>
      <CityTown>Toronto</CityTown>
    </Address>
    <Address>
      <PersonId>1</PersonId>
      <Street>180 Redwood ST</Street>
      <PostCode>94102-3280</PostCode>
      <CityTown>San Francisco</CityTown>
    </Address>
    <Address>
      <PersonId>2</PersonId>
      <Street>212 Harbord St</Street>
      <PostCode>M5S1H6</PostCode>
      <CityTown>Toronto</CityTown>
    </Address>
    <Address>
      <PersonId>3</PersonId>
      <Street>1100 Danforth Ave</Street>
      <PostCode>M4J1N2</PostCode>
      <CityTown>Toronto</CityTown>
    </Address>
    <Address>
      <PersonId>3</PersonId>
      <Street>6 Green St</Street>
      <PostCode>94111-1402</PostCode>
      <CityTown>San Francisco</CityTown>
    </Address>
  </Addresses>
</Persons-Addresses>
]]>
        </programlisting>
      </figure>
      <para>
There are two ways to do this:
      </para>
      <itemizedlist>
        <listitem>
          <para>
        Use a record mapping section with two
            <link xlink:href="../guide/index.html#sx:groupBy">sx:groupBy</link>
        sections. In this case the implementation will
    buffer the records in memory until the first group is finished, and only then
    do the second.
          </para>
        </listitem>
        <listitem>
          <para>
        Within a record mapping section, read the flat file twice, first inserting
        the person data content, and then inserting the address content.
          </para>
        </listitem>
      </itemizedlist>

      <para>
    Taking the first approach, the resources script looks like this:
      </para>
      <figure id="resources-persons1.xml">
        <title>Resources script resources-persons1.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="personsAddresses">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="persons"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:flatFile id="personsData">
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordType ref="persons"/>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordContent id="persons">
    <sx:flatFileReader>
      <sx:flatFile ref="personsData"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="personsAddressesMapping"/>
  </sx:recordContent>

  <sx:flatRecordType id="persons" name="persons">
    <sx:positionalField name="PersonId" width="9"/>
    <sx:positionalField name="Name" width="11"/>
    <sx:positionalField name="FirstName" width="16"/>
    <sx:positionalField name="Street" width="20"/>
    <sx:positionalField name="PostCode" width="12"/>
    <sx:positionalField name="CityTown" width="20" />
  </sx:flatRecordType>

  <sx:recordMapping id="personsAddressesMapping">
    <Persons-Addresses>
      <Persons>
        <sx:groupBy fields="PersonId">
          <Person>
            <sx:fieldElementMap field="PersonId" element="PersonId"/>
            <sx:fieldElementMap field="Name" element="Name"/>
            <sx:fieldElementMap field="FirstName" element="FirstName"/>
            <sx:onRecord/>
          </Person>
        </sx:groupBy>
      </Persons>
      <Addresses>
        <sx:onRecord>
          <Address>
            <sx:fieldElementMap field="PersonId" element="PersonId"/>
            <sx:fieldElementMap field="Street" element="Street"/>
            <sx:fieldElementMap field="PostCode" element="PostCode"/>
            <sx:fieldElementMap field="CityTown" element="CityTown"/>
          </Address>
        </sx:onRecord>
      </Addresses>
    </Persons-Addresses>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
    Taking the second approach, the resources script looks like this:
      </para>
      <figure id="resources-persons2.xml">
        <title>Resources script resources-persons2.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="personsAddresses">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="persons"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:flatFile id="personsData">
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordType ref="persons"/>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordContent id="persons">
    <sx:recordMapping ref="personsAddressesMapping"/>
  </sx:recordContent>

  <sx:flatRecordType id="persons" name="persons">
    <sx:positionalField name="PersonId" width="9"/>
    <sx:positionalField name="Name" width="11"/>
    <sx:positionalField name="FirstName" width="16"/>
    <sx:positionalField name="Street" width="20"/>
    <sx:positionalField name="PostCode" width="12"/>
    <sx:positionalField name="CityTown" width="20" />
  </sx:flatRecordType>

  <sx:recordMapping id="personsAddressesMapping">
    <Persons-Addresses>
      <sx:nestedContent>
        <sx:recordContent>
          <sx:flatFileReader>
            <sx:flatFile ref="personsData"/>
          </sx:flatFileReader>
          <sx:recordMapping ref="personsMapping"/>
        </sx:recordContent>
      </sx:nestedContent>
      <sx:nestedContent>
        <sx:recordContent>
          <sx:flatFileReader>
            <sx:flatFile ref="personsData"/>
          </sx:flatFileReader>
          <sx:recordMapping ref="addressesMapping"/>
        </sx:recordContent>
      </sx:nestedContent>
    </Persons-Addresses>
  </sx:recordMapping>

  <sx:recordMapping id="personsMapping">
    <Persons>
      <sx:groupBy fields="PersonId">
        <Person>
          <sx:fieldElementMap field="PersonId" element="PersonId"/>
          <sx:fieldElementMap field="Name" element="Name"/>
          <sx:fieldElementMap field="FirstName" element="FirstName"/>
          <sx:onRecord/>
        </Person>
      </sx:groupBy>
    </Persons>
  </sx:recordMapping>

  <sx:recordMapping id="addressesMapping">
    <Addresses>
      <sx:onRecord>
        <Address>
          <sx:fieldElementMap field="PersonId" element="PersonId"/>
          <sx:fieldElementMap field="Street" element="Street"/>
          <sx:fieldElementMap field="PostCode" element="PostCode"/>
          <sx:fieldElementMap field="CityTown" element="CityTown"/>
        </Address>
      </sx:onRecord>
    </Addresses>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following:
        <itemizedlist>
          <listitem>
Since you only want to show distinct persons in the persons section, group by PersonId.
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run the two examples on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i data/persons.txt -o output/persons1.xml -r resources-persons1.xml 
    personsAddresses 
]]>
        </programlisting>
        <programlisting>
          <![CDATA[
servingxml -i data/persons.txt -o output/persons2.xml -r resources-persons2.xml 
    personsAddresses 
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Converting a directory of books positional files to XML files (all books)</title>
      <titleabbrev>books directory to XML</titleabbrev>
      <indexterm>
        <primary>directory</primary>
        <secondary>reading</secondary>
      </indexterm>
      <indexterm>
        <primary>directory</primary>
        <secondary>writing</secondary>
      </indexterm>
      <indexterm>
        <primary>regular expressions</primary>
        <secondary>match and replace</secondary>
      </indexterm>
      <para>
The example below shows how to process
all the files in the
        <filename>data</filename>
directory matching the regular expression "books.*[.]txt",
convert them from positional flat file formats to XML files, and write them out to the
        <filename>output</filename>
directory.
      </para>
      <para>
As before, the input is a directory of files.
      </para>
      <figure id="directory">
        <title>Directory containing input files</title>
        <programlisting>
          <![CDATA[
[.]                     countries.csv           multivalued-field.csv
[..]                    countries.xsd           plans.txt
3545_JH4DA3_4_H_.xml    country-record.xsd      tasks.csv
bad-countries.csv       exotics.txt             timesheets.csv
books.20040613.txt      hot-record.xsd          trades.txt
books.20040802.txt      hot-record.xsx
books.txt               hot.txt
books.xml               messages.properties]]>
        </programlisting>
      </figure>
      <para>
We want to take the positional files whose names match the regular expression
        <code>"(books.*)[.]txt"</code>
and convert them all to XML files.
      </para>

      <figure id="books-output-files">
        <title>Books XML output files.</title>
        <programlisting>
          <![CDATA[
books.xml            books.20040802.xml
books.20040613.xml
]]>
        </programlisting>
      </figure>

      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-allbooks.xml">
        <title>Resources script resources-allbooks.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">
   
  <sx:service id="all-books">
    <sx:recordStream>
      <sx:directoryReader directory="data">
        <sx:fileFilter pattern="books.*[.]txt"/>
      </sx:directoryReader>
      <sx:processRecord>
        <sx:parameter name="output-file">
          <sx:findAndReplace searchFor ="(books.*)[.]txt" replaceWith ="$1.xml">
            <sx:toString value="{name}"/>
          </sx:findAndReplace>
        </sx:parameter>
        <sx:serialize>
          <sx:xsltSerializer>
            <sx:fileSink directory="output" file="{$output-file}"/>
          </sx:xsltSerializer>
          <sx:transform>
            <sx:content ref="books"/>
          </sx:transform>
        </sx:serialize>
      </sx:processRecord>
    </sx:recordStream>
  </sx:service>

  <sx:recordContent id="books">
    <sx:flatFileReader>
      <sx:fileSource directory="{parentDirectory}" file="{name}"/>
      <sx:flatFile ref="booksFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="booksToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="booksFile">
    <sx:flatFileHeader>
      <sx:flatRecordType ref="bookType"/>
      <sx:annotationRecord/>
    </sx:flatFileHeader>
    <sx:flatFileBody>
      <sx:flatRecordType ref="bookType"/>
    </sx:flatFileBody>
    <sx:flatFileTrailer>
      <sx:annotationRecord></sx:annotationRecord>
      <sx:annotationRecord>This is a trailer record</sx:annotationRecord>
    </sx:flatFileTrailer>
  </sx:flatFile>      

  <sx:flatRecordType id="bookType" name="bookType">
    <sx:positionalField name="category" label="Category" width="1"/>
    <sx:positionalField name="author" label="Author" width="30"/>
    <sx:positionalField name="title" label="Title" width="30"/>
    <sx:positionalField name="price" label="Price" width="10" justify="right"/>
  </sx:flatRecordType>

  <sx:recordMapping id="booksToXmlMapping">
    <myns:books xmlns:myns="http://mycompany.com/mynames/" 
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="url2">
      <sx:onRecord>
        <myns:book>
          <sx:fieldAttributeMap field="category" attribute="categoryCode"/>
          <sx:fieldElementMap field="title" element="myns:title"/>  
          <sx:fieldElementMap field="author" element="myns:author"/>
          <sx:fieldElementMap field="price" element="myns:price"/>
        </myns:book>  
      </sx:onRecord>
    </myns:books>
  </sx:recordMapping>  
  
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml  -r resources-allbooks.xml all-books
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Converting a flat file to multiple XML book files (multiple books)</title>
      <titleabbrev>multiple XML book files</titleabbrev>
      <indexterm>
        <primary>XML files</primary>
        <secondary>multiple</secondary>
      </indexterm>
      <para>
The example below shows how to process one flat file and produce multiple XML 
output files.
      </para>
      <para>
The input file is shown below.
      </para>
      <figure id="books.txt">
        <title>Books input file</title>
        <programlisting>
          <![CDATA[
CAuthor                        Title                              Price ISBN

FCharles Bukowski              Factotum                           22.95 0876852630
FSergei Lukyanenko             The Night Watch                    17.99 0434014125
FAndrew Crumey                 Mr Mee                             22.00 0312282354
CSteven John Metsker           Building Parsers with Java         39.95 0201719622

This is a trailer record
]]>
        </programlisting>
      </figure>
      <para>
We want to produce multiple files like the one shown below, with filenames
differentiated by the isbn number.
      </para>

      <figure id="book-0876852630.xml">
        <title>Book XML output file book-0876852630.xml.</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<myns:book xmlns:myns="http://mycompany.com/mynames/" 
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
           categoryCode="F">
  <myns:title>Factotum</myns:title>
  <myns:author>Charles Bukowski</myns:author>
  <myns:price>22.95</myns:price>
  <myns:isbn>0876852630</myns:isbn>
</myns:book>
]]>
        </programlisting>
      </figure>

      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-books_multiple.xml">
        <title>Resources script resources-books_multiple.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0"?>

<sx:resources xmlns:sx="http://www.servingxml.com/core"
                     xmlns:myns="http://mycompany.com/mynames/" >

  <sx:service id="books">
    <sx:transform>
      <sx:content ref="books"/>
      <sx:processSubtree path="/myns:books/myns:book">
        <sx:parameter name="isbn" select="myns:isbn"/>
        <sx:serialize>
          <sx:xsltSerializer> 
            <sx:fileSink directory="output" file="book-{$isbn}.xml"/> 
          </sx:xsltSerializer> 
        </sx:serialize>
      </sx:processSubtree>
    </sx:transform>
  </sx:service>
  
  <!--
  This sx:flatFileReader element does not specify a stream source, so 
  the source will default to the file specified with the -i option on the command line.
  -->
  <sx:recordContent id="books">
    <sx:flatFileReader>
      <sx:flatFile ref="booksFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="booksToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="booksFile">
    <sx:flatFileHeader>
      <sx:flatRecordType ref="bookType"/>
      <sx:annotationRecord/>
    </sx:flatFileHeader>
    <sx:flatFileBody>
      <sx:flatRecordType ref="bookType"/>
    </sx:flatFileBody>
    <sx:flatFileTrailer>
      <sx:annotationRecord></sx:annotationRecord>
      <sx:annotationRecord>This is a trailer record</sx:annotationRecord>
    </sx:flatFileTrailer>
  </sx:flatFile>

  <sx:flatRecordType id="bookType" name="bookType">
    <sx:positionalField name="category" label="Category" width="1"/>
    <sx:positionalField name="author" label="Author" width="30"/>
    <sx:positionalField name="title" label="Title" width="30"/>
    <sx:positionalField name="price" label="Price" width="10" justify="right"/>
    <sx:positionalField name="isbn" label="ISBN" start="73" width="10"/>
  </sx:flatRecordType>

  <sx:recordMapping id="booksToXmlMapping">
    <myns:books xmlns:myns="http://mycompany.com/mynames/"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="url2">
      <sx:onRecord>
        <myns:book>
          <sx:fieldAttributeMap field="category" attribute="categoryCode"/>
          <sx:fieldElementMap field="title" element="myns:title"/>
          <sx:fieldElementMap field="author" element="myns:author"/>
          <sx:fieldElementMap field="price" element="myns:price"/>
          <sx:fieldElementMap field="isbn" element="myns:isbn"/>
        </myns:book>
      </sx:onRecord>
    </myns:books>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-books_multiple.xml -i data/books.txt books 
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Converting a flat file to multiple XML documents with default namespace
  prefixes (multiple default ns)
      </title>
      <titleabbrev>multiple default ns</titleabbrev>
      <indexterm>
        <primary>XML files</primary>
        <secondary>multiple</secondary>
      </indexterm>
      <indexterm>
        <primary>XML files</primary>
        <secondary>default
                                         namespace</secondary>
      </indexterm>
      <para>
The example below shows how to process
one flat file and produce multiple XML documents with default namespace
prefixes.
      </para>
      <para>
The input file is the same as in the previous example.
      </para>
      <figure id="books.txt">
        <title>Books input file</title>
        <programlisting>
          <![CDATA[
CAuthor                        Title                              Price ISBN

FCharles Bukowski              Factotum                           22.95 0876852630
FSergei Lukyanenko             The Night Watch                    17.99 0434014125
FAndrew Crumey                 Mr Mee                             22.00 0312282354
CSteven John Metsker           Building Parsers with Java         39.95 0201719622

This is a trailer record
]]>
        </programlisting>
      </figure>
      <para> This time we want to produce multiple files like the one shown below,
with a default namespace prefix.
      </para>

      <figure id="book-0876852630.xml">
        <title>Book XML output file book-with-default-ns-0156028972.xml.</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<book xmlns="http://mycompany.com/mynames/"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      categoryCode="F">
   <title>Gun, with Occasional Music</title>
   <author>Jonathan Lethem</author>
   <price>17.99</price>
   <isbn>0156028972</isbn>
</book>
]]>
        </programlisting>
      </figure>

      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-multiple_default_ns.xml">
        <title>Resources script resources-multiple_default_ns.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:myns="http://mycompany.com/mynames/">

  <sx:service id="books">
    <sx:transform>
      <sx:content ref="books"/>
      <sx:processSubtree path="/myns:books/myns:book">
        <sx:parameter name="isbn" select="myns:isbn"/>
        <sx:serialize>
          <sx:xsltSerializer>
            <sx:fileSink directory="output" file="book-with-default-ns-{$isbn}.xml"/>
            <sx:outputProperty name="indent" value="yes"/>
          </sx:xsltSerializer>
        </sx:serialize>
      </sx:processSubtree>
    </sx:transform>
  </sx:service>
  
  <!--
  This sx:flatFileReader element does not specify a stream source, so 
  the source will default to the file specified with the -i option on the command line.
  -->
  <sx:recordContent id="books">
    <sx:flatFileReader>
      <sx:flatFile ref="booksFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="booksToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="booksFile">
    <sx:flatFileHeader>
      <sx:flatRecordType ref="bookType"/>
      <sx:annotationRecord/>
    </sx:flatFileHeader>
    <sx:flatFileBody>
      <sx:flatRecordType ref="bookType"/>
    </sx:flatFileBody>
    <sx:flatFileTrailer>
      <sx:annotationRecord></sx:annotationRecord>
      <sx:annotationRecord>This is a trailer record</sx:annotationRecord>
    </sx:flatFileTrailer>
  </sx:flatFile>

  <sx:flatRecordType id="bookType" name="bookType">
    <sx:positionalField name="category" label="Category" width="1"/>
    <sx:positionalField name="author" label="Author" width="30"/>
    <sx:positionalField name="title" label="Title" width="30"/>
    <sx:positionalField name="price" label="Price" width="10" justify="right"/>
    <sx:positionalField name="isbn" label="ISBN" start="73" width="10"/>
  </sx:flatRecordType>

  <sx:recordMapping id="booksToXmlMapping">
    <books xmlns="http://mycompany.com/mynames/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="url2">
      <sx:onRecord>
        <book>
          <sx:fieldAttributeMap field="category" attribute="myns:categoryCode"/>
          <sx:fieldElementMap field="title" element="myns:title"/>
          <sx:fieldElementMap field="author" element="myns:author"/>
          <sx:fieldElementMap field="price" element="myns:price"/>
          <sx:fieldElementMap field="isbn" element="myns:isbn"/>
        </book>
      </sx:onRecord>
    </books>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <section>
        <title>Remarks</title>
        <itemizedlist>
          <listitem>
            <para>Note that the root element in the
              <link xlink:href="../guide/index.html#sx:recordMapping">sx:recordMapping</link>
section
            contains a default namespace declaration, which will appear in the
            output XML, and which will have the effect that XML names belonging
            to the namespace "http://mycompany.com/mynames/" will be output
            without an explicit prefix.
            </para>
          </listitem>
          <listitem>
            <para>Note that the
              <link xlink:href="../guide/index.html#sx:fieldAttributeMap">sx:fieldAttributeMap</link>
and
              <link xlink:href="../guide/index.html#sx:fieldElementMap">sx:fieldElementMap</link>
elements use the
              <sgmltag>myns</sgmltag>
prefix to associate attribute and
                    element names with the namespace
                    "http://mycompany.com/mynames/".  The prefix is resolved
                    against the nearest in-scope prefix declaration for
              <sgmltag>myns</sgmltag>
, which happens to be the one in the
              <link xlink:href="../guide/index.html#sx:resources">sx:resources</link>
element.
            Since this declaration does not appear inside the record mapping
            section, it is used only to associate a name with a namespace, not
            for serialization.
            </para>
          </listitem>
          <listitem>
            <para>If a prefix were omitted in an attribute or element mapping,
             say on
              <sgmltag>title</sgmltag>
, that element would belong to no
                    namespace, all others would belong to the default namespace,
                    and the output would become
              <programlisting>
                <![CDATA[
<book xmlns="http://mycompany.com/mynames/"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      categoryCode="F">
   <title xmlns="">Gun, with Occasional Music</title>
   <author>Jonathan Lethem</author>
   <price>17.99</price>
   <isbn>0156028972</isbn>
</book>

]]>
              </programlisting>
            </para>
          </listitem>
        </itemizedlist>
      </section>

      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-multiple_default_ns.xml -i data/books.txt books 
]]>
        </programlisting>
      </para>
    </section>
  </section>
  <section>
    <title>Flat Files with Multibyte Characters</title>
    <section>
      <title>A UTF-8 positional flat file with double byte characters
      </title>
      <titleabbrev>UTF-8 double byte</titleabbrev>
      <indexterm>
        <primary>UTF-8</primary>
        <secondary>double byte</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
positional flat file with multi-byte encoding to XML.
      </para>
      <para>
The input file is a positional flat file containing the following hex UTF-8 byte
input.
      </para>
      <figure id="doubleByte.txt" xreflabel="doubleByte.txt flat file">
        <title>Input flat file doubleByte.txt</title>
        <programlisting>
          <![CDATA[
41414242 43430A41 C3964242 43430A
]]>
        </programlisting>
      </figure>
      <para>
    The two byte sequence C396 represents the single character Ö.
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="doubleByte.xml">
        <title>Output XML file doubleByte.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8" ?> 
<document>
  <documentData>
    <param1>AA</param1> 
    <param2>BB</param2> 
    <param3>CC</param3> 
  </documentData>
  <documentData>
    <param1>AÖ</param1> 
    <param2>BB</param2> 
    <param3>CC</param3> 
  </documentData>
</document>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-doubleByte.xml">
        <title>Resources script resources-doubleByte.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="convert">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="data"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="data">
    <sx:flatFileReader>
      <sx:flatFile ref="flatfile"/>
      <sx:defaultStreamSource encoding="UTF-8"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="recordmap"/>
  </sx:recordContent>

  <sx:flatFile id="flatfile">
    <sx:flatFileBody>
      <sx:flatRecordType ref="recordtype"/>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:flatRecordType id="recordtype">
    <sx:positionalField name="param1" width="2"/>
    <sx:positionalField name="param2" width="2"/>
    <sx:positionalField name="param3" width="2"/>
  </sx:flatRecordType>

  <sx:recordMapping id="recordmap">
    <document>
      <sx:onRecord>
        <documentData>
          <sx:fieldElementMap element="param1" field="param1"/>
          <sx:fieldElementMap element="param2" field="param2"/>
          <sx:fieldElementMap element="param3" field="param3"/>
        </documentData>
      </sx:onRecord>
    </document>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-doubleByte.xml -i data/doubleByte.dat 
    -o output/doubleByte.xml convert
]]>
        </programlisting>
      </para>
    </section>
  </section>

  <section>
    <title>Fixed Width Fields, Multiple Record Types, Line Delimited</title>

    <section id="trades-eg" xreflabel="trades">
      <title>Converting a flat file with multiple record formats to XML (trades)</title>
      <titleabbrev>trades (positional) to XML</titleabbrev>
      <indexterm>
        <primary>date</primary>
        <secondary>convert to ISO 8601 format</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>positional</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>multiple record format</secondary>
      </indexterm>
      <indexterm>
        <primary>regular expressions</primary>
        <secondary>match and replace</secondary>
      </indexterm>
      <indexterm>
        <primary>parameter</primary>
        <secondary>default value</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file with multiple record formats to XML.
      </para>
      <para>
The input file is a positional flat file.
      </para>
      <figure id="trades.txt">
        <title>Input flat file trades.txt</title>
        <programlisting>
          <![CDATA[
TR000103/25/2005 1:50:00This is a trade record
TN0002X1234A child transaction
TN0003X1235Another child transaction
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="trades.xml">
        <title>Output XML file trades.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<trades feed="LONDON">
  <trade id="0001">
    <trade-date>2005-03-25T01:50:00.000-05:00</trade-date>
    <description>This is a trade record</description>
    <transaction id="0002">
      <reference>X1234</reference>
      <description>A child transaction</description>
    </transaction>
    <transaction id="0003">
      <reference>X1235</reference>
      <description>Another child transaction</description>
    </transaction>
  </trade>
</trades>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-trades.xml">
        <title>Resources script resources-trades.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0"?>
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="trades">
    <sx:parameter name="feed">
      <sx:defaultValue>NY</sx:defaultValue>
    </sx:parameter>
    <sx:serialize>
      <sx:transform>
        <sx:content ref="trades"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="trades">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:urlSource url="data/trades.txt"/>
        <sx:flatFile ref="tradesFlatFile"/>
      </sx:flatFileReader>
      <sx:combineRecords recordType="composite" repeatingGroup="detail"
                                             startTest="sx:current//record_type='TR'"
                                             endTest="sx:current//record_type='TR'">
        <sx:newField name="id" select="detail/trade/id"/>
      </sx:combineRecords>
    </sx:recordStream>
    <sx:recordMapping ref="tradesToXmlMapping"/>
  </sx:recordContent>

  <sx:recordMapping id="tradesToXmlMapping">
    <trades>
      <sx:fieldAttributeMap value="{$feed}" attribute="feed"/>
      <sx:onRecord recordType="composite">
        <trade>
          <sx:fieldAttributeMap field="id" attribute="id"/>
          <sx:subrecordMapping repeatingGroup="detail">
            <sx:onRecord recordType="trade">
              <sx:elementMap element="trade-date">
                <sx:convertToDateTime format="MM/dd/yyyy H:mm:ss">
                  <sx:concat separator=" "> 
                    <sx:toString value="{trade_date}"/>
                    <sx:toString value="{trade_time}"/>
                  </sx:concat>
                </sx:convertToDateTime>
              </sx:elementMap>
              <sx:fieldElementMap field="description" element="description"/>
            </sx:onRecord>
            <sx:onRecord recordType="transaction">
              <transaction>
                <sx:fieldAttributeMap field="id" attribute="id"/>
                <sx:fieldElementMap field="reference" element="reference"/>
                <sx:fieldElementMap field="description" element="description"/>
              </transaction>
            </sx:onRecord>
          </sx:subrecordMapping>
        </trade>
      </sx:onRecord>
    </trades>
  </sx:recordMapping>

  <sx:flatFile id="tradesFlatFile">
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:positionalField name="record_type" width="2"/>
        <sx:when test="record_type='TR'">
          <sx:flatRecordType name="trade">
            <sx:positionalField name="record_type" width="2"/>
            <sx:positionalField name="id" width="4"/>
            <sx:positionalField name="trade_date" width="10"/>
            <sx:positionalField name="trade_time" width="8"/>
            <sx:positionalField name="description" width="30"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="record_type='TN'">
          <sx:flatRecordType name="transaction">
            <sx:positionalField name="record_type" width="2"/>
            <sx:positionalField name="id" width="4"/>
            <sx:positionalField name="reference" width="5"/>
            <sx:positionalField name="description" width="30"/>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points about the content of the<![CDATA[<sx:elementMap element="trade-date">]]> element.
        <itemizedlist>
          <listitem>
The inner
            <link xlink:href="../guide/index.html#sx:concat">sx:concat</link>
element concatenates the date and time fields from the record,
separating them with a space.
          </listitem>
          <listitem>
The
            <link xlink:href="../guide/index.html#sx:convertDate">sx:convertDate</link>
element converts the datetime value into something close to an
ISO 8601 date, where the input and output formats follow the syntax specified for the
            <ulink url="http://java.sun.com/j2se/1.3/docs/api/java/text/SimpleDateFormat.html">JDK SimpleDateFormat</ulink>
class.
          </listitem>
          <listitem>
The outer
            <link xlink:href="../guide/index.html#sx:findAndReplace">sx:findAndReplace</link>
            element inserts a colon into the time format.
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-trades.xml -o output/trades.xml trades feed=LONDON
]]>
        </programlisting>
      </para>
    </section>

    <section id="CONV-eg" xreflabel="CONV">
      <title>Converting a flat file to XML with header, detail, and summary records (CONV)</title>
      <titleabbrev>conv (positional) to XML</titleabbrev>
      <indexterm>
        <primary>group</primary>
        <secondary>inner</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>positional</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>single record format</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file with header, detail, and summary records to XML.
      </para>
      <para>
The input file is a positional flat file with variable record layouts.
      </para>
      <figure id="tasks.csv">
        <title>Input flat file CONV_in.dat</title>
        <programlisting>
          <![CDATA[
90112345678abcdefg1000001 
100SURNAME1 GIVEN1 A 
100SURNAME2 GIVEN2 B 
3011111111AB111111 
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="tasks.xml">
        <title>Output XML file CONV.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<Submission>
  <Header>
    <record_type>901</record_type>
    <sbmt_ref_id>abcdefg</sbmt_ref_id>
    <trnmtr_tcd>1</trnmtr_tcd>
    <summ_cnt>000001</summ_cnt>
  </Header>
  <All>
    <Level1>
      <Detail>
        <snm>SURNAME1</snm>
        <gvn_nm>GIVEN1</gvn_nm>
        <init>A</init>
      </Detail>
      <Detail>
        <snm>SURNAME2</snm>
        <gvn_nm>GIVEN2</gvn_nm>
        <init>B</init>
      </Detail>
      <Summary>
        <bn>1111111AB111111</bn>
      </Summary>
    </Level1>
  </All>
</Submission>
]]></programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-CONV.xml">
        <title>Resources script resources-CONV.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:msv="http://www.servingxml.com/extensions/msv">

  <sx:service id="CONV">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="CONV"/>
        <sx:removeEmptyElements elements="*"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="CONV">
    <sx:flatFileReader>
      <sx:urlSource url="data/CONV_in.dat"/>
      <sx:flatFile ref="CONVFlatFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="CONVToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="CONVFlatFile">
    <sx:commentStarter value="#"/>
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:positionalField name="record_type" width="3"/>
        <sx:when test="record_type='901'">
          <sx:flatRecordType name="header">
            <sx:positionalField name="record_type" width="3"/>
            <sx:positionalField name="trnmtr_nbr" width="8"/>
            <sx:positionalField name="sbmt_ref_id" width="7"/>
            <sx:positionalField name="trnmtr_tcd" width="1"/>
            <sx:positionalField name="summ_cnt" width="6"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="record_type='100'">
          <sx:flatRecordType name="detail">
            <sx:positionalField name="record_type" width="3"/>
            <sx:positionalField name="snm" width="9"/>
            <sx:positionalField name="gvn_nm" width="7"/>
            <sx:positionalField name="init" width="1"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="record_type='301'">
          <sx:flatRecordType name="summary">
            <sx:positionalField name="record_type" width="3"/>
            <sx:positionalField name="bn" width="15"/>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="CONVToXmlMapping">
    <Submission>
      <sx:onRecord recordType="header">
        <Header>
          <sx:fieldElementMap field="record_type" element="record_type"/>
          <sx:fieldElementMap field="sbmt_ref_id" element="sbmt_ref_id"/>
          <sx:fieldElementMap field="trnmtr_tcd" element="trnmtr_tcd"/>
          <sx:fieldElementMap field="summ_cnt" element="summ_cnt"/>
        </Header>
      </sx:onRecord>
      <sx:innerGroup startTest="sx:current/detail or sx:current/summary"
                     endTest="not(sx:current/detail or sx:current/summary)">
        <All>
          <Level1>
            <sx:onRecord recordType='detail'>
              <Detail>
                <sx:fieldElementMap field="snm" element="snm"/>
                <sx:fieldElementMap field="gvn_nm" element="gvn_nm"/>
                <sx:fieldElementMap field="init" element="init"/>
              </Detail>
            </sx:onRecord>
            <sx:onRecord recordType="summary">
              <Summary>
                <sx:fieldElementMap field="bn" element="bn"/>
              </Summary>
            </sx:onRecord>
          </Level1>
        </All>
      </sx:innerGroup>
    </Submission>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -o output/CONV.xml -r resources-CONV.xml CONV
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Converting a positional file to XML using a record filter (hot 1)</title>
      <titleabbrev>hot (preliminaries)</titleabbrev>
      <indexterm>
        <primary>record filter</primary>
        <secondary>custom</secondary>
      </indexterm>
      <indexterm>
        <primary>record filter</primary>
        <secondary>schema validation</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>positional</secondary>
      </indexterm>
      <para>
This is the first of two examples that map the
        <filename>hot.txt</filename>
flat file to XML.
      </para>
      <para>
The input file is a variable record positional file.
      </para>
      <figure id="hot.txt">
        <title>Input flat file hot.txt</title>
        <programlisting>
          <![CDATA[
BFH01value01
BCH02value02
BOH03value03
BKT06value04issue
BKP84value05A6USD2
BOT93value06
BOT94value07
BOH03value08
BKT06value09issue
BKP84value10A6CAD2
BOT93value11
BKT06value12refund
BKP84value13A6USD2
BOT93value14
BOT94value15
BCT95value16
BFT99value17
]]>
        </programlisting>
      </figure>
      <para>
This file has variant record types.  The first five characters identify the record type,
and the next seven characters represent a hypothetical attribute.  The BKT06 and
BKP84 records have additional fields.
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="hot1.xml">
        <title>Output XML file hot1.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8" ?>
<hot>
   <BFH01 attr1="value01"/>
   <BCH02 attr1="value02"/>
   <BOH03 attr1="value03"/>
   <BKT06 attr1="value04"/>
   <BKP84 attr1="value05" amount="1.66" currency="USD"/>
   <BOT93 attr1="value06"/>
   <BOT94 attr1="value07"/>
   <BOH03 attr1="value08"/>
   <BKT06 attr1="value09"/>
   <BKP84 attr1="value10" amount="2.46" currency="CAD"/>
   <BOT93 attr1="value11"/>
   <BKT06 attr1="value12"/>
   <BKP84 attr1="value13" amount="2.27" currency="USD"/>
   <BOT93 attr1="value14"/>
   <BOT94 attr1="value15"/>
   <BCT95 attr1="value16"/>
   <BFT99 attr1="value17"/>
</hot>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>

      <figure id="flatfile-hot.xml">
        <title>flatfile-hot.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:flatFile id="hotFlatFile">
    <sx:commentStarter value="#"/>
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:positionalField name="record-type" width="5"/>
        
        <sx:when  test="record-type='BKP84'">
          <sx:flatRecordType name="bkp84">
            <sx:positionalField name="record-type-prefix"  width="3"/>
            <sx:positionalField name="record-type"  start="1" width="5"/>
            <sx:positionalField name="value" width="7"/>
            <sx:positionalField name="amount" width="2"/>
            <sx:positionalField name="currency" width="3"/>
            <sx:positionalField name="precision" width="1"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="record-type='BKT06'">
          <sx:flatRecordType name="bkt06">
            <sx:positionalField name="record-type-prefix"  width="3"/>
            <sx:positionalField name="record-type"  start="1" width="5"/>
            <sx:positionalField name="value" width="7"/>
            <sx:positionalField name="type" width="6"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:otherwise>
          <sx:flatRecordType name="other">
            <sx:positionalField name="record-type-prefix"  width="3"/>
            <sx:positionalField name="record-type" start="1" width="5"/>
            <sx:positionalField name="value" width="7"/>
          </sx:flatRecordType>
        </sx:otherwise>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>
    
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
The values in the
        <code>bkp84</code>
record need to be transformed as follows:
      </para>
      <itemizedlist>
        <listitem>
          <para>
The amount field is encoded as a hexadecimal value and needs to be converted to a
decimal value.
          </para>
        </listitem>
        <listitem>
          <para>
The resulting decimal value needs to be converted to the specified precision.
          </para>
        </listitem>
      </itemizedlist>
      <para>
In the hot 1 example in this section, we transform the values using a
        <link xlink:href="../guide/index.html#sx:customRecordFilter">sx:customRecordFilter</link>
 element to define a custom record filter written in Java.  In the hot 2 example in the next section, we take a
different approach, transforming the values within an XPath select expression against the record
fields, making use of extension calls to static Java functions.
      </para>
      <figure id="hot-record.xsd">
        <title>XML Schema file hot-record.xsd</title>
        <programlisting>
          <![CDATA[
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <!-- This element's name matches the value of the name attribute in the "bkp84" sx:flatFileRecordType. -->
  <xs:element name="bkp84" type="bkp84Type"/>
  
  <!-- This element's name matches the value of the name attribute in the "bkt06" sx:flatFileRecordType. -->
  <xs:element name="bkt06" type="bkt06Type"/>
  
  <!-- This element's name matches the value of the name attribute in the "other" sx:flatFileRecordType. -->
  <xs:element name="other" type="otherType"/>

  <xs:complexType name="bkp84Type">
    <xs:sequence>
      <xs:element name="record-type-prefix" type="xs:string"/>
      <xs:element name="record-type" type="xs:string"/>
      <xs:element name="value" type="xs:string"/>
      <xs:element name="amount" type="xs:hexBinary"/>
      <xs:element name="currency" type="xs:string"/>
      <xs:element name="precision" type="xs:nonNegativeInteger"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="bkt06Type">
    <xs:sequence>
      <xs:element name="record-type-prefix" type="xs:string"/>
      <xs:element name="record-type" type="xs:string"/>
      <xs:element name="value" type="xs:string"/>
      <xs:element name="type" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="otherType">
    <xs:sequence>
      <xs:element name="record-type-prefix" type="xs:string"/>
      <xs:element name="record-type" type="xs:string"/>
      <xs:element name="value" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>
]]>
        </programlisting>
      </figure>
      <figure id="resources-hot1.xml">
        <title>Resources script resources-hot1.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:msv="http://www.servingxml.com/extensions/msv">

  <sx:include href="flatfile-hot.xml"/>

  <sx:service id="hot1">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="hot1"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="hot1">
    <sx:flatFileReader>
      <sx:flatFile ref="hotFlatFile"/>
    </sx:flatFileReader>
    <msv:recordValidator>
      <sx:urlSource url="data/hot-record.xsd"/>
    </msv:recordValidator>
    <sx:customRecordFilter class="flat2xml.HotRecordFilter"/>
    <sx:discardHandler>
      <sx:log message="{$sx:message}"/>
    </sx:discardHandler>
    <sx:recordMapping ref="hot1ToXmlMapping"/>
  </sx:recordContent>

  <sx:recordMapping id="hot1ToXmlMapping">
    <hot>
      <sx:onRecord recordType="bkp84">
        <sx:elementMap element="{record-type}">
          <sx:fieldAttributeMap field="value" attribute="attr1"/>
          <sx:fieldAttributeMap field="calculatedAmount"  attribute="amount"/>
          <sx:fieldAttributeMap field="currency" attribute="currency"/>
        </sx:elementMap>
      </sx:onRecord>
      <sx:onRecord recordType="bkt06">
        <sx:elementMap element="{record-type}">
          <sx:fieldAttributeMap field="value" attribute="attr1"/>
        </sx:elementMap>
      </sx:onRecord>
      <sx:onRecord recordType="other">
        <sx:elementMap element="{record-type}">
          <sx:fieldAttributeMap field="value" attribute="attr1"/>
        </sx:elementMap>
      </sx:onRecord>
    </hot>
  </sx:recordMapping>
    
</sx:resources>
]]>
        </programlisting>
      </figure>
      <figure id="HotRecordFilter">
        <title>HotRecordFilter class</title>
        <programlisting>
          <![CDATA[
package flat2xml;

import com.servingxml.app.ServiceContext;
import com.servingxml.components.recordio.AbstractRecordFilter;
import com.servingxml.app.Flow;
import com.servingxml.util.Name;
import com.servingxml.util.QualifiedName;
import com.servingxml.util.ServingXmlException;
import com.servingxml.util.record.Record;
import com.servingxml.util.record.RecordBuilder;

public class HotRecordFilter extends AbstractRecordFilter {
  private static final Name BKP84_RECORD_TYPE = new QualifiedName("bkp84");
  private static final Name AMOUNT_NAME = new QualifiedName("amount");
  private static final Name PRECISION_NAME = new QualifiedName("precision");
  private static final Name CALCULATED_AMOUNT_NAME = new QualifiedName("calculatedAmount");
  
  public void writeRecord(ServiceContext context, Flow flow) 
   {

    Record record = flow.getRecord();
    Flow newFlow = flow;
    if (record.getRecordType().getName().equals(BKP84_RECORD_TYPE)) {
      RecordBuilder recordBuilder = new RecordBuilder(record);
      String amountString = record.getString(AMOUNT_NAME);
      if (amountString == null) {
        throw new ServingXmlException("amount is NULL");
      }
      String precisionString = record.getString(PRECISION_NAME);
      if (precisionString == null) {
        throw new ServingXmlException("precision is NULL");
      }
      int amount = Integer.parseInt(amountString,16);
      int precision = Integer.parseInt(precisionString);
      double calculatedAmount = (double)amount/Math.pow(10.0,(double)precision);
      recordBuilder.setDouble(CALCULATED_AMOUNT_NAME,calculatedAmount);
      record = recordBuilder.toRecord();
      newFlow = flow.replaceRecord(context, record);
    }

    super.writeRecord(context, newFlow);
  }
}  
]]></programlisting>
      </figure>
      <para>
You can run this example on the command line by
        <itemizedlist>
          <listitem>
Compiling the Java class
            <code>HotRecordFilter</code>
and copying
the resulting
            <filename>.class</filename>
file into the
            <filename>dir/classes</filename>
directory
          </listitem>
          <listitem>
Entering the command
            <programlisting>
              <![CDATA[
servingxml -r resources-hot1.xml -i data/hot.txt -o output/hot1.xml hot1
]]>
            </programlisting>
          </listitem>
        </itemizedlist>
      </para>
    </section>

    <section id="hot2-eg" xreflabel="hot2">
      <title>Converting a positional file to XML with outer and inner grouping (hot 2)</title>
      <titleabbrev>hot (positional) to XML (grouped)</titleabbrev>
      <indexterm>
        <primary>group</primary>
        <secondary>inner</secondary>
      </indexterm>
      <indexterm>
        <primary>group</primary>
        <secondary>outer</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>positional</secondary>
      </indexterm>
      <indexterm>
        <primary>XSLT extensions</primary>
        <secondary>using</secondary>
      </indexterm>
      <para>
This version of the hot example shows how to convert a
flat file to XML document with outer and inner grouping.   Each row in the flat 
file is validated with Sun's multi schema validator, and the row is discarded if 
an error is encountered.
      </para>
      <para>
This examples illustrates the
        <link xlink:href="../guide/index.html#sx:innerGroup">sx:innerGroup</link>
and
        <link xlink:href="../guide/index.html#sx:innerGroup">sx:outerGroup</link>
elements.  Both elements use
the
        <sgmltag class="attribute">startTest</sgmltag>
and
        <sgmltag class="attribute">endTest</sgmltag>
attributes to
define the beginning and end of a group through XPath boolean expressions applied to records.  They
differ in that
        <link xlink:href="../guide/index.html#sx:innerGroup">sx:innerGroup</link>
will never allow any descendent
elements to be produced unless a group is recognized at its level, whereas a
        <link xlink:href="../guide/index.html#sx:innerGroup">sx:outerGroup</link>
will only suppress content between this element and
the next succeeding grouping element.
      </para>
      <para>
The
        <filename>resources-hot2.xml</filename>
file defines the record mapping for this version of
the hot example.  The
        <code>BFH01</code>
record type marks the beginning of a group of level 1,
the
        <code>BFT99</code>
s mark the end.  The
        <code>BCH02</code>
s mark
the beginning of a group of level 2, the
        <code>BCT95</code>
s mark the end.
The
        <code>BOH03</code>
marks the beginning of a group of level 3, the
        <code>BOT94s</code>
mark the end.
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="hot2.xml">
        <title>Output XML file hot2.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8" ?>
<hot>
   <BFH01 attr1="value01"/>
   <periods>
      <period>
         <BCH02s>
            <BCH02 attr1="value02"/>
         </BCH02s>
         <agents>
            <agent>
               <BOH03 attr1="value03"/>
               <issues>
                  <issue>
                     <BKT06 attr1="value04"/>
                     <BKP84 attr1="value05" amount="1.66" currency="USD"/>
                  </issue>
                  <BOT93s>
                     <BOT93 attr1="value06"/>
                  </BOT93s>
               </issues>
               <BOT94s>
                  <BOT94 attr1="value07"/>
               </BOT94s>
            </agent>
            <agent>
               <BOH03 attr1="value08"/>
               <issues>
                  <issue>
                     <BKT06 attr1="value09"/>
                     <BKP84 attr1="value10" amount="2.46" currency="CAD"/>
                  </issue>
                  <BOT93s>
                     <BOT93 attr1="value11"/>
                  </BOT93s>
               </issues>
               <refunds>
                  <refund>
                     <BKT06 attr1="value12"/>
                     <BKP84 attr1="value13" amount="2.27" currency="USD"/>
                  </refund>
                  <BOT93s>
                     <BOT93 attr1="value14"/>
                  </BOT93s>
               </refunds>
               <BOT94s>
                  <BOT94 attr1="value15"/>
               </BOT94s>
            </agent>
         </agents>
         <BCT95s>
            <BCT95 attr1="value16"/>
         </BCT95s>
      </period>
   </periods>
   <BFT99s>
      <BFT99 attr1="value17"/>
   </BFT99s>
</hot>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-hot2.xml">
        <title>Resources script resources-hot2.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:msv="http://www.servingxml.com/extensions/msv"
              xmlns:integer="java.lang.Integer" xmlns:math="java.lang.Math">

  <sx:include href="flatfile-hot.xml"/>

  <sx:service id="hot2">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="hot2"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="hot2">
    <sx:flatFileReader>
      <sx:flatFile ref="hotFlatFile"/>
    </sx:flatFileReader>
    <msv:recordValidator>
      <sx:urlSource url="data/hot-record.xsd"/>
    </msv:recordValidator>
    <sx:discardHandler>
      <sx:log message="{$sx:message}"/>
    </sx:discardHandler>
    <sx:recordMapping ref="hot2ToXmlMapping"/>
  </sx:recordContent>

  <sx:recordMapping id="hot2ToXmlMapping">
    <hot>
      <sx:outerGroup startTest="sx:previous//record-type='BFH01'" 
                     endTest="sx:current//record-type='BFT99'">
        <periods>
          <sx:outerGroup startTest="sx:current//record-type='BCH02'"
                         endTest="sx:previous//record-type='BCT95'">
            <period>
              <sx:outerGroup startTest="sx:previous//record-type='BCH02'" 
                             endTest="sx:current//record-type='BCT95'">
                <agents>
                  <sx:outerGroup startTest="sx:current//record-type='BOH03'" 
                                 endTest="sx:previous//record-type='BOT94'">
                    <agent>
                      <sx:groupChoice>
                        <sx:innerGroup startTest="sx:current//record-type-prefix='BFH'" 
                                       endTest="sx:previous//record-type-prefix='BFH'">
                          <sx:onRecord>
                            <sx:elementMap element="{record-type}">
                              <sx:fieldAttributeMap field="value" attribute="attr1"/>
                            </sx:elementMap>
                          </sx:onRecord>
                        </sx:innerGroup>
                        <sx:innerGroup startTest="sx:current//record-type-prefix='BOH'" 
                                       endTest="sx:previous//record-type-prefix='BOH'">
                          <sx:onRecord>
                            <sx:elementMap element="{record-type}">
                              <sx:fieldAttributeMap field="value" attribute="attr1"/>
                            </sx:elementMap>
                          </sx:onRecord>
                        </sx:innerGroup>
                        <sx:innerGroup startTest="sx:current//record-type-prefix='BFT'" 
                                       endTest="sx:previous//record-type-prefix='BFT'">
                          <sx:elementMap element="{record-type}s">
                            <sx:onRecord>
                              <sx:elementMap element="{record-type}">
                                <sx:fieldAttributeMap field="value" attribute="attr1"/>
                              </sx:elementMap>
                            </sx:onRecord>
                          </sx:elementMap>
                        </sx:innerGroup>
                        <sx:innerGroup startTest="sx:current//record-type-prefix='BCT'" 
                                       endTest="sx:previous//record-type-prefix='BCT'">
                          <sx:elementMap element="{record-type}s">
                            <sx:onRecord>
                              <sx:elementMap element="{record-type}">
                                <sx:fieldAttributeMap field="value" attribute="attr1"/>
                              </sx:elementMap>
                            </sx:onRecord>
                          </sx:elementMap>
                        </sx:innerGroup>
                        <sx:innerGroup startTest="sx:current//record-type='BOT94'" 
                                       endTest="sx:previous//record-type='BOT94'">
                          <sx:elementMap element="{record-type}s">
                            <sx:onRecord>
                              <sx:elementMap element="{record-type}">
                                <sx:fieldAttributeMap field="value" attribute="attr1"/>
                              </sx:elementMap>
                            </sx:onRecord>
                          </sx:elementMap>
                        </sx:innerGroup>
                        <sx:innerGroup startTest="sx:current//record-type='BCH02'" 
                                       endTest="sx:previous//record-type='BOH03'">
                          <sx:elementMap element="{record-type}s">
                            <sx:onRecord>
                              <sx:elementMap element="{record-type}">
                                <sx:fieldAttributeMap field="value" attribute="attr1"/>
                              </sx:elementMap>
                            </sx:onRecord>
                          </sx:elementMap>
                        </sx:innerGroup>
                        <sx:innerGroup startTest="sx:current//record-type='BKT06'" 
                                       endTest="sx:previous//record-type='BOT93'">
                          <sx:elementMap element="{type}s">
                            <sx:groupChoice>
                              <sx:innerGroup startTest="sx:current//record-type='BKT06'"
                                             endTest="sx:previous//record-type='BKP84'">
                                <sx:elementMap element="{type}">
                                  <sx:onRecord recordType="bkt06">
                                    <sx:elementMap element="{record-type}">
                                      <sx:fieldAttributeMap field="value" attribute="attr1"/>
                                    </sx:elementMap>
                                  </sx:onRecord>
                                  <sx:onRecord recordType="bkp84">
                                    <sx:elementMap element="{record-type}">
                                      <sx:fieldAttributeMap field="value" attribute="attr1"/>
                                      <sx:fieldAttributeMap select="integer:valueOf(amount,16) div math:pow(10,precision)"  attribute="amount"/>
                                      <sx:fieldAttributeMap field="currency" attribute="currency"/>
                                    </sx:elementMap>
                                  </sx:onRecord>
                                </sx:elementMap>
                              </sx:innerGroup>
                              <sx:innerGroup startTest="sx:current//record-type-prefix='BOT'" 
                                             endTest="sx:previous//record-type-prefix='BOT'">
                                <sx:elementMap element="{record-type}s">
                                  <sx:onRecord>
                                    <sx:elementMap element="{record-type}">
                                      <sx:fieldAttributeMap field="value" attribute="attr1"/>
                                    </sx:elementMap>
                                  </sx:onRecord>
                                </sx:elementMap>
                              </sx:innerGroup>
                            </sx:groupChoice>
                          </sx:elementMap>
                        </sx:innerGroup>
                      </sx:groupChoice>
                    </agent>
                  </sx:outerGroup>
                </agents>
              </sx:outerGroup>
            </period>
          </sx:outerGroup>
        </periods>
      </sx:outerGroup>
    </hot>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-hot2.xml -i data/hot.txt -o output/hot2.xml hot2
]]>
        </programlisting>
      </para>
    </section>

    <section id="variable-field-widths" xreflabel="variable-field-widths">
      <title>Converting a positional flat file with variable field widths to
  XML</title>
      <titleabbrev>variable field widths</titleabbrev>
      <indexterm>
        <primary>flat
file</primary>
        <secondary>positional</secondary>
        <tertiary>variable
                                                 width fields</tertiary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file with variable field widths to XML.
      </para>
      <para>
The input file is a positional flat file.
      </para>
      <figure id="testWidth.txt">
        <title>Input flat file testWidth.txt</title>
        <programlisting>
          <![CDATA[
TX#00000000010016This is a remarkXXXXXXXXXX
TX#0000000002              
TX#0000000003    YYYYYYYYYY
TX#00000000030004TestZZZZZZZZZZ
]]>
        </programlisting>
      </figure>
      <para>
    This file contains an optional positional field called "remarksText".
    The field size varies and when the field exists it's width is specified
    using the value of its preceding field called "remarksSize". When no
    "remarksText" exists, 4 space characters
    are specified as "remarksSize" in the file directly followed by the value of
    "followingField".
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="testWidth.xml">
        <title>Output XML file testWidth.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Doc>
  <Transaction>
    <Reference>0000000001</Reference>
    <Remarks>This is a remark</Remarks>
    <FollowingField>XXXXXXXXXX</FollowingField>
  </Transaction>
  <Transaction>
    <Reference>0000000002</Reference>
    <Remarks/>
    <FollowingField/>
  </Transaction>
  <Transaction>
    <Reference>0000000003</Reference>
    <Remarks/>
    <FollowingField>YYYYYYYYYY</FollowingField>
  </Transaction>
  <Transaction>
    <Reference>0000000003</Reference>
    <Remarks>Test</Remarks>
    <FollowingField>ZZZZZZZZZZ</FollowingField>
  </Transaction>
</Doc>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-testWidth.xml">
        <title>Resources script resources-testWidth.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="testWidth">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="data"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="data">
    <sx:flatFileReader>
      <sx:flatFile ref="flatFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="segmentsToXml"/>
  </sx:recordContent>

  <sx:flatFile id="flatFile">
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:positionalField name="tag" width="3"/>
        <sx:when test="tag='TX#'">
          <sx:flatRecordType name="transaction">
            <sx:positionalField name="recordType" width="3"/>
            <sx:positionalField name="reference" width="10"/>
            <sx:positionalField name="remarksSize" width="4">
              <sx:defaultValue value="0"/>
            </sx:positionalField>
            <sx:positionalField name="remarksText" width="{remarksSize}"/>
            <sx:positionalField name="followingField" width="10"/>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="segmentsToXml">
    <Doc>
      <sx:innerGroup startTest="sx:current/transaction">
        <Transaction>
          <sx:fieldElementMap field="reference"  element="Reference"/>
          <sx:fieldElementMap field="remarksText" element="Remarks"/>
          <sx:fieldElementMap field="followingField" element="FollowingField"/>
        </Transaction>
      </sx:innerGroup>
    </Doc>
  </sx:recordMapping>
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following.
        <itemizedlist>
          <listitem>When the "remarksSize" is not specified as shown in row
2 and 3 of the flat file, the value for {remarksSize} must default to
            <code>0</code>
. The "remarksSize" positional field definition therefore
  contains a
            <link xlink:href="../guide/index.html#sx:defaultValue">sx:defaultValue</link>
element, which supplies the default.
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-testWidth.xml -i testWidth.txt -o output/testWidth.xml testWidth
]]>
        </programlisting>
      </para>
    </section>
    <section id="repeat-header-info-eg" xreflabel="repeat header">
      <title>Repeat Header Information in the XML</title>
      <titleabbrev>repeat header in XML</titleabbrev>
      <indexterm>
        <primary>flat to XML</primary>
        <secondary>repeat header in XML</secondary>
      </indexterm>
      <indexterm>
        <primary>parameter</primary>
        <secondary>within groups</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file to XML with header information repeated when processing the other
records.
      </para>
      <para>
The record input is
      </para>
      <figure id="repeated-header-info.txt">
        <title>Record Input</title>
        <programlisting>
         <![CDATA[
1A
2B
3C
2D
3E
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="repeated_header_info.xml">
        <title>Output XML file repeated_header_info.xml</title>
        <programlisting>
          <![CDATA[
<doc>
  <b attr="B">
    <c attr="C">A</c>
  </b>
  <b attr="D">
    <c attr="E">A</c>
  </b>
</doc>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-repeatHeader.xml">
        <title>Resources script resources-repeatHeader.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="hut">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="HutContent"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="HutContent">
    <sx:flatFileReader ref="HutFlatFileReader"/>
    <sx:recordMapping ref="hut2ToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="HutFlatFile">
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:positionalField name="record-type" start="1" width="1"/>
        <sx:when test='record-type="1"'>
          <sx:flatRecordType id="R1" name="R1">
            <sx:positionalField name="TOTO" start="2" width="1"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test='record-type="2"'>
          <sx:flatRecordType id="R2" name="R2">
            <sx:positionalField name="TATA" start="2" width="1"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test='record-type="3"'>
          <sx:flatRecordType id="R3" name="R3">
            <sx:positionalField name="TITI" start="2" width="1"/>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:flatFileReader id="HutFlatFileReader">
    <sx:inlineSource>1A
2B
3C
2D
3E</sx:inlineSource>
    <sx:flatFile ref="HutFlatFile"/>
  </sx:flatFileReader>

  <sx:recordMapping id="hut2ToXmlMapping">
    <doc>
      <sx:parameter name="temp" value="{TOTO}"/>
      <sx:outerGroup startTest="sx:current/R2">
        <b>
          <sx:fieldAttributeMap value="{TATA}" attribute="attr"/>
          <sx:onRecord recordType="R3">
            <sx:fieldElementMap value="{$temp}" element="c">
              <sx:fieldAttributeMap value="{TITI}" attribute="attr"/>
            </sx:fieldElementMap>
          </sx:onRecord>
        </b>
      </sx:outerGroup>
    </doc>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>Note the parameter declaration for "temp" in the record mapping 
        section.  This parameter declaration occurs immediately below the 
        document element, which represents a grouping of all records.  Within a
        group, <code>ServingXML</code> ServingXML binds the parameter name to 
        the record that begins the grouping section, in this case the first 
        header record in the input.
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-repeatheader.xml -o output/repeated_header_info.xml hut 
]]>
        </programlisting>
      </para>
    </section>
  </section>
  <section>
    <title>Fixed Width Fields, Multiple Record Types, Repeating Groups, Line Delimited</title>
    <section>
      <title>Converting fixed position records with repeating groups to XML (segments)</title>
      <titleabbrev>segments</titleabbrev>
      <indexterm>
        <primary>repeating groups</primary>
      </indexterm>
      <para>
This shows how to convert fixed position records that contain repeatable/optional fixed parts identified by tags.
      </para>
      <para>
The input file is a positional file.
      </para>
      <figure id="segments.txt" xreflabel="segments.txt flat file">
        <title>Input flat file segments.txt</title>
        <programlisting>
          <![CDATA[
Z01xxxyyyZ02aaaabbccZ02aaaabbccZ01xxxyyy
]]>
        </programlisting>
      </figure>
      <para>
Note the following:
        <itemizedlist>
          <listitem>
The whole record is positional, but contains "segments" that do not have a terminator but a starting tag and a fixed length.
          </listitem>
          <listitem>
Z01 and Z02 are "segment"-tags and a,b,x and y are positional fields within the "segment"
          </listitem>
        </itemizedlist>
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="segments.xml">
        <title>Output XML file segments.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<Recs>
  <Rec>
    <Z01>
      <xxx>xxx</xxx>
      <yyy>yyy</yyy>
    </Z01>
    <Z02>
      <aaaa>aaaa</aaaa>
      <bb>bb</bb>
      <cc>cc</cc>
    </Z02>
    <Z02>
      <aaaa>aaaa</aaaa>
      <bb>bb</bb>
      <cc>cc</cc>
    </Z02>
    <Z01>
      <xxx>xxx</xxx>
      <yyy>yyy</yyy>
    </Z01>
  </Rec>
</Recs>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-segments.xml">
        <title>Resources script resources-segments.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="segments">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="data"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="data">
    <sx:flatFileReader>
      <sx:urlSource url="data/segments.txt"/>
      <sx:flatFile ref="flatFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="segmentsToXml"/>
  </sx:recordContent>

  <sx:flatFile id="flatFile">
    <sx:flatFileBody>
      <sx:flatRecordType name="rec">
        <sx:repeatingGroup name="segments">
          <sx:flatRecordTypeChoice>
            <sx:positionalField name="tag" width="3"/>
            <sx:when test="tag='Z01'">
              <sx:flatRecordType name="Z01">
                <sx:positionalField name="tag" width="3"/>
                <sx:positionalField name="xxx" width="3"/>
                <sx:positionalField name="yyy" width="3"/>
              </sx:flatRecordType>
            </sx:when>
            <sx:otherwise>
              <sx:flatRecordType name="Z02">
                <sx:positionalField name="tag" width="3"/>
                <sx:positionalField name="aaaa" width="4"/>
                <sx:positionalField name="bb" width="2"/>
                <sx:positionalField name="cc" width="2"/>
              </sx:flatRecordType>
            </sx:otherwise>
          </sx:flatRecordTypeChoice>
        </sx:repeatingGroup>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="segmentsToXml">
    <Recs>
      <sx:onRecord>
        <Rec>
          <sx:subrecordMapping repeatingGroup="segments">
            <sx:onRecord recordType="Z01">
              <Z01>
                <sx:fieldElementMap field="xxx" element="xxx"/>
                <sx:fieldElementMap field="yyy"  element="yyy"/>
              </Z01>
            </sx:onRecord>
            <sx:onRecord recordType="Z02">
              <Z02>
                <sx:fieldElementMap field="aaaa" element="aaaa"/>
                <sx:fieldElementMap field="bb" element="bb"/>
                <sx:fieldElementMap field="cc" element="cc"/>
              </Z02>
            </sx:onRecord>
          </sx:subrecordMapping>
        </Rec>
      </sx:onRecord>
    </Recs>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -o output/segments.xml -r resources-segments.xml 
    segments 
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Mapping multiple repeating groups to XML (students-fix)</title>
      <titleabbrev>students</titleabbrev>
      <indexterm>
        <primary>repeating groups</primary>
        <secondary>fixed</secondary>
      </indexterm>
      <para>
Suppose you have the following positional file of students, their course grades, and their addresses.
      </para>
      <figure id="students-fix.txt" xreflabel="students-fix.txt flat file">
        <title>Input flat file students-fix.txt</title>
        <programlisting>
          <![CDATA[
JANEENGLC-MATHA+1972BLUECHICAGOILATLANTAGA
]]>
        </programlisting>
      </figure>
      <para>
The file has the following layout.
      </para>
      <informaltable colsep="0">
        <tr>
          <td>name</td>
          <td>4 characters</td>
        </tr>
        <tr>
          <td>subject-grade</td>
          <td>repeating group, repeats twice</td>
        </tr>
        <tr>
          <td>year-born</td>
          <td>4 characters</td>
        </tr>
        <tr>
          <td>favorite-color</td>
          <td>4 characters</td>
        </tr>
        <tr>
          <td>address</td>
          <td>repeating group, repeats twice</td>
        </tr>
      </informaltable>
      <para>
You want the XML output to look as follows.
      </para>
      <figure id="students-fix.xml">
        <title>Output XML file students-fix.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<StudentGrades>
  <StudentGrade>
    <Name>JANE</Name>
    <SubjectGrade>
      <Subject>ENGL</Subject>
      <Grade>C-</Grade>
    </SubjectGrade>
    <SubjectGrade>
      <Subject>MATH</Subject>
      <Grade>A+</Grade>
    </SubjectGrade>
    <YearBorn>1972</YearBorn>
    <FavoriteColor>BLUE</FavoriteColor>
    <Address>
      <City>CHICAGO</City>
      <State>IL</State>
    </Address>
    <Address>
      <City>ATLANTA</City>
      <State>GA</State>
    </Address>
  </StudentGrade>
</StudentGrades>
]]>
        </programlisting>
      </figure>
      <para>The required resources script is
      </para>
      <figure id="resources-students-fix.xml">
        <title>Resources script resources-students-fix.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="students">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="students-content"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="students-content">
    <sx:flatFileReader>
      <sx:flatFile ref="students-file"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="students-mapping"/>
  </sx:recordContent>

  <sx:flatFile id="students-file">
    <sx:flatFileBody>
      <sx:flatRecordType name="student">
        <sx:positionalField name="name" width="4"/>
        <sx:repeatingGroup name="grades" count="2">
          <sx:flatRecordType name="subject-grade">
            <sx:positionalField name="subject" width="4"/>
            <sx:positionalField name="grade" width="2"/>
          </sx:flatRecordType>
        </sx:repeatingGroup>
        <sx:positionalField name="year-born" width="4"/>
        <sx:positionalField name="favorite-color" width="4"/>
        <sx:repeatingGroup name="addresses" count="2">
          <sx:flatRecordType name="address">
            <sx:positionalField name="city" width="7"/>
            <sx:positionalField name="state" width="2"/>
          </sx:flatRecordType>
        </sx:repeatingGroup>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="students-mapping">
    <StudentGrades>
      <sx:onRecord>
        <StudentGrade>
          <sx:fieldElementMap field="name" element="Name"/>
          <sx:subrecordMapping repeatingGroup="grades">
            <sx:onRecord>
              <SubjectGrade>
                <sx:fieldElementMap field="subject" element="Subject"/>
                <sx:fieldElementMap field="grade" element="Grade"/>
              </SubjectGrade>
            </sx:onRecord>
          </sx:subrecordMapping>
          <sx:fieldElementMap field="year-born" element="YearBorn"/>
          <sx:fieldElementMap field="favorite-color" element="FavoriteColor"/>
          <sx:subrecordMapping repeatingGroup="addresses">
            <sx:onRecord>
              <Address>
                <sx:fieldElementMap field="city" element="City"/>
                <sx:fieldElementMap field="state" element="State"/>
              </Address>
            </sx:onRecord>
          </sx:subrecordMapping>
        </StudentGrade>
      </sx:onRecord>
    </StudentGrades>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml  -r resources-students-fix.xml -i data/students-fix.txt -o output/students-fix.xml 
    students
]]>
        </programlisting>
      </para>
    </section>

  </section>

  <section>
    <title>Fixed Width Fields, Single Record Type, No End-of-Line Delimiters</title>
    <section id="non_delimited_book_orders" xreflabel="non_delimited_book_orders">
      <title>Converting a flat file with a single record type, but no end-of-line delimiters, to XML (non-delimited book orders)</title>
      <titleabbrev>non-delimited book orders to XML</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>no end-of-line delimiters</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>single record format</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file with a single record format, but no end-of-line delimiters, to XML.
      </para>
      <para>
The input file is a fixed field width flat file.
      </para>
      <figure id="non_delimited_book_orders.txt">
        <title>Input flat file non_delimited_book_orders.txt</title>
        <programlisting>
          <![CDATA[
CAuthor                        Title                              Price InvoiceNo InvoiceDate       FCharles Bukowski              Factotum                           22.95 001  12/Mar/2005            FSergei Lukyanenko             The Night Watch                    17.99 002  13/Mar/2005            FAndrew Crumey                 Mr Mee                             22.00 003 14/June/2005            CSteven John Metsker           Building Parsers with Java         39.95 004 15/June/2005            This is a trailer record                                                                            
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="non_delimited_book_orders.xml">
        <title>Output XML file book_orders.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<book-orders>
  <book-type>
    <category>F</category>
    <author>Charles Bukowski</author>
    <title>Factotum</title>
    <price>22.95</price>
    <invoiceno>001</invoiceno>
    <invoicedate>12/Mar/2005</invoicedate>
    <filler/>
  </book-type>
  <book-type>
    <category>F</category>
    <author>Sergei Lukyanenko</author>
    <title>The Night Watch</title>
    <price>17.99</price>
    <invoiceno>002</invoiceno>
    <invoicedate>13/Mar/2005</invoicedate>
    <filler/>
  </book-type>
  <book-type>
    <category>F</category>
    <author>Andrew Crumey</author>
    <title>Mr Mee</title>
    <price>22.00</price>
    <invoiceno>003</invoiceno>
    <invoicedate>14/June/2005</invoicedate>
    <filler/>
  </book-type>
  <book-type>
    <category>C</category>
    <author>Steven John Metsker</author>
    <title>Building Parsers with Java</title>
    <price>39.95</price>
    <invoiceno>004</invoiceno>
    <invoicedate>15/June/2005</invoicedate>
    <filler/>
  </book-type>
</book-orders>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-non_delimited_book_orders.xml">
        <title>Resources script resources-non_delimited_book_orders.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">
   
  <sx:service id="book-orders"> 
    <sx:serialize>
      <sx:transform>
        <sx:content ref="book-orders"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="book-orders" name="book-orders">
    <sx:flatFileReader>
      <sx:flatFile ref="books-flatfile"/>
    </sx:flatFileReader>
  </sx:recordContent>
  
  <sx:flatFile id="books-flatfile" lineDelimited="false">
    <sx:flatFileHeader>
      <sx:flatRecordType ref="book-type"/>
    </sx:flatFileHeader>
    <sx:flatFileBody>
      <sx:flatRecordType ref="book-type"/>
    </sx:flatFileBody>
    <sx:flatFileTrailer>
      <sx:annotationRecord width="100">This is a trailer record</sx:annotationRecord>
    </sx:flatFileTrailer>
  </sx:flatFile>      

  <sx:flatRecordType id="book-type" name="book-type">
    <sx:positionalField name="category" width="1"/>
    <sx:positionalField name="author" width="30"/>
    <sx:positionalField name="title" width="30"/>
    <sx:positionalField name="price" width="10" justify="right"/>
    <sx:positionalField name="invoiceno" width="4" justify="right"/>
    <sx:positionalField name="invoicedate" width="13" justify="right"/>
    <sx:positionalField name="filler" width="12"/>
  </sx:flatRecordType>
  
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points.
        <itemizedlist>
          <listitem>
The
            <link xlink:href="../guide/index.html#sx:recordContent">sx:recordContent</link>
element has a
            <sgmltag class="attribute">lineDelimited</sgmltag>
attribute set to
            <code>false</code>
.
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-non_delimited_book_orders.xml 
  -i data/non_delimited_book_orders.txt
  -o output/book_orders.xml  book-orders
]]>
        </programlisting>
      </para>
    </section>
  </section>

  <section>
    <title>Fixed Width Fields, Multiple Record Types, No End-of-Line Delimiters</title>
    <section id="non_delimited_variant_trades" xreflabel="non_delimited_variant_trades">
      <title>Converting a flat file with multiple record formats, but no end-of-line delimiters, to XML (non-delimited trades)</title>
      <titleabbrev>non-delimited trades to XML</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>no end-of-line delimiters</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file</primary>
        <secondary>multiple record format</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file with multiple record formats, but no end-of-line delimiters, to XML.
      </para>
      <para>
The input file is a fixed field width flat file.
      </para>
      <figure id="non_delimited_variant_trades.txt">
        <title>Input flat file non_delimited_variant_trades.txt</title>
        <programlisting>
          <![CDATA[
TR000103/25/2005 1:50:00This is a trade record        TN0002X1234A child transaction           TN0003X1235Another child transaction    
]]>
        </programlisting>
      </figure>
      <para>
The desired output is shown below.
      </para>
      <figure id="non_delimited_variant_trades.xml">
        <title>Output XML file trades.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<trades>
  <trade id="0001">
    <trade-date>2005-03-25T01:50:00.000-05:00</trade-date>
    <description>This is a trade record</description>
  </trade>
  <transaction id="0002">
    <reference>X1234</reference>
    <description>A child transaction</description>
  </transaction>
  <transaction id="0003">
    <reference>X1235</reference>
    <description>Another child transaction</description>
  </transaction>
</trades>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-non_delimited_variant_trades.xml">
        <title>Resources script resources-non_delimited_variant_trades.xm</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="trades">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="trades"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="trades">
    <sx:flatFileReader>
      <sx:urlSource url="data/non_delimited_variant_trades.txt"/>
      <sx:flatFile ref="trades-flatfile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="trades-xml-mapping"/>
  </sx:recordContent>

  <sx:flatFile id="trades-flatfile" name="trades" lineDelimited="false">
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:positionalField name="record_type" width="2"/>
        <sx:when test="record_type='TR'">
          <sx:flatRecordType name="trade">
            <sx:positionalField name="record_type" width="2"/>
            <sx:positionalField name="id" width="4"/>
            <sx:positionalField name="trade_date" width="10"/>
            <sx:positionalField name="trade_time" width="8"/>
            <sx:positionalField name="description" width="30"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="record_type='TN'">
          <sx:flatRecordType name="transaction">
            <sx:positionalField name="record_type" width="2"/>
            <sx:positionalField name="id" width="4"/>
            <sx:positionalField name="reference" width="5"/>
            <sx:positionalField name="description" width="30"/>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="trades-xml-mapping">
    <trades>
      <sx:onRecord recordType="trade">
        <trade>
          <sx:fieldAttributeMap field="id" attribute="id"/>
          <sx:elementMap element="trade-date">
            <sx:convertToDateTime format="MM/dd/yyyy H:mm:ss">
              <sx:concat separator=" ">
                <sx:toString value="{trade_date}"/>
                <sx:toString value="{trade_time}"/>
              </sx:concat>
            </sx:convertToDateTime>
          </sx:elementMap>
          <sx:fieldElementMap field="description" element="description"/>
        </trade>
      </sx:onRecord>
      <sx:onRecord recordType="transaction">
        <transaction>
          <sx:fieldAttributeMap field="id" attribute="id"/>
          <sx:fieldElementMap field="reference" element="reference"/>
          <sx:fieldElementMap field="description" element="description"/>
        </transaction>
      </sx:onRecord>
    </trades>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points.
        <itemizedlist>
          <listitem>
The
            <link xlink:href="../guide/index.html#sx:recordContent">sx:recordContent</link>
element has a
            <sgmltag class="attribute">lineDelimited</sgmltag>
attribute set to
            <code>false</code>
.
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-non_delimited_variant_trades.xml 
  -o output/trades.xml trades 
]]>
        </programlisting>
      </para>
    </section>

    <section id="special-char-eg" xreflabel="special-char">
      <title>Converting a flat file with special characters to XML (special char)</title>
      <titleabbrev>special char to XML</titleabbrev>
      <indexterm>
        <primary>special char</primary>
      </indexterm>
      <indexterm>
        <primary>flat file field</primary>
        <secondary>binary</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file with special characters to XML.
      </para>
      <para>
The input file is a flat file with two adjacent records (no line delimiters):
        <itemizedlist>
          <listitem>
            <para>A record beginning with the hexadecimal value 03, followed by the text "1111111"
            </para>
          </listitem>
          <listitem>
            <para>A record beginning with the hexadecimal value 04, followed by the text "John Smith"
            </para>
          </listitem>
        </itemizedlist>
The two hexadecimal values are needed to differentiate the record type, but these valued cannot be written as
        <![CDATA[&#x03;]]> and<![CDATA[&#x04;]]> in XML, as these are not valid XML characters.
      </para>

      <para>
The desired output is shown below.
      </para>
      <figure id="specialChar.xml">
        <title>Output XML file specialChar.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<transaction>
  <R03>
    <firstField>03</firstField>
    <CLIENUM>1111111</CLIENUM>
  </R03>
  <R04>
    <firstField>04</firstField>
    <NAME>John Smith</NAME>
  </R04>
</transaction>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-specialChar.xml">
        <title>Resources script resources-specialChar.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="transaction">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="transactionDoc"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="transactionDoc" name="transaction">
    <sx:flatFileReader>
      <sx:flatFile ref="transactionFile"/>
    </sx:flatFileReader>
  </sx:recordContent>

  <sx:flatFile id="transactionFile" lineDelimited="false">
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:binaryField name="firstField" width="1"/>
        <sx:when test="firstField='03'">
          <sx:flatRecordType id="R03" name="R03">
            <sx:binaryField name="firstField" label="firstField" width="1" />
            <sx:positionalField name="CLIENUM" label="CLIENUM" width="007" />
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="firstField='04'">
          <sx:flatRecordType id="R04" name="R04">
            <sx:binaryField name="firstField" label="firstField" width="1" />
            <sx:positionalField name="NAME" label="NAME" width="020" />
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note that the first field of each record is declared as an
        <link xlink:href="../guide/index.html#sx:binaryField">sx:binaryField</link>
.
The string rendering of this field is as an hexidecimal value.
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml  -r resources-specialChar.xml -i data/specialChar.txt 
  -o output/specialChar.xml transaction
]]>
        </programlisting>
      </para>
    </section>
    <section id="packed-decimal-to-xml" xreflabel="packed-decimal-to-xml">
      <title>Converting a flat file containing Cobol packed decimal data to XML (packed decimal to XML)</title>
      <titleabbrev>packed decimal to XML</titleabbrev>
      <indexterm>
        <primary>flat file field</primary>
        <secondary>packed decimal</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
non-delimited flat file containing Cobol packed decimal data to XML.
      </para>
      <para>
The input file, shown below, is encoded in ebcdic, except for the price field,
which is expressed as a Cobol packed decimal number
        <code>99999999.99</code>
.
      </para>
      <figure id="books-positional.txt" xreflabel="books.txt">
        <title>Input positional flat file books.txt</title>
        <programlisting>
          <![CDATA[
CAuthor                        Title                              Price

FCharles Bukowski              Factotum                           22.95
FSergei Lukyanenko             The Night Watch                    17.99
FAndrew Crumey                 Mr Mee                             22.00
CSteven John Metsker           Building Parsers with Java         39.95

This is a trailer record
]]>
        </programlisting>
      </figure>

      <para>
The desired output is shown below.
      </para>
      <figure id="books.xml">
        <title>Output XML file books.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<myns:books xmlns:myns="http://mycompany.com/mynames/" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="url2">
  <myns:book categoryCode="F">
    <myns:title>Factotum</myns:title>
    <myns:author>Charles Bukowski</myns:author>
    <myns:price>22.95</myns:price>
  </myns:book>
  <myns:book categoryCode="F">
    <myns:title>The Night Watch</myns:title>
    <myns:author>Sergei Lukyanenko</myns:author>
    <myns:price>17.99</myns:price>
  </myns:book>
  <myns:book categoryCode="F">
    <myns:title>Mr Mee</myns:title>
    <myns:author>Andrew Crumey</myns:author>
    <myns:price>22.00</myns:price>
  </myns:book>
  <myns:book categoryCode="C">
    <myns:title>Building Parsers with Java</myns:title>
    <myns:author>Steven John Metsker</myns:author>
    <myns:price>39.95</myns:price>
  </myns:book>
</myns:books>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-books_ebcdic_packed.xml">
        <title>Resources script resources-books_ebcdic_packed.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="books-ebcdic-packed2xml"> 
    <sx:serialize>
      <sx:transform>
        <sx:content ref="books"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>
  
  <!--
  This sx:flatFileReader element does not specify a stream source, so 
  the source will default to the file specified with the -i option on the command line.
  -->
  <sx:recordContent id="books">
    <sx:flatFileReader>
      <sx:flatFile ref="booksFile"/>
      <sx:defaultStreamSource encoding="Cp1047"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="booksToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="booksFile" lineDelimited="false">
    <sx:flatFileBody>
      <sx:flatRecordType ref="bookType"/>
    </sx:flatFileBody>
  </sx:flatFile>      

  <sx:flatRecordType id="bookType" name="bookType">
    <sx:positionalField name="category" label="Category" width="1"/>
    <sx:positionalField name="author" label="Author" width="30"/>
    <sx:positionalField name="title" label="Title" width="30"/>
    <sx:packedDecimalField name="price" label="Price" digitCount="10" decimalPlaces="2"/>
  </sx:flatRecordType>
  
  <sx:recordMapping id="booksToXmlMapping">
    <myns:books xmlns:myns="http://mycompany.com/mynames/" 
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="url2">
      <sx:onRecord>
        <myns:book>
          <sx:fieldAttributeMap field="category" attribute="categoryCode"/>
          <sx:fieldElementMap field="title" element="myns:title"/>  
          <sx:fieldElementMap field="author" element="myns:author"/>
          <sx:fieldElementMap field="price" element="myns:price"/>
        </myns:book>  
      </sx:onRecord>
    </myns:books>
  </sx:recordMapping>  
  
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note that the last field of each record is declared as an
        <link xlink:href="../guide/index.html#sx:packedDecimalField">sx:packedDecimalField</link>
.
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml  -r resources-books_ebcdic_packed.xml 
  -i data/books_ebcdic_packed.dat 
  -o  output/books.xml    books-ebcdic-packed2xml
]]>
        </programlisting>
      </para>
    </section>
  </section>

  <section>
    <title>Logical Record Consists of Multiple Physical Records</title>

    <section id="smf" xreflabel="smf">
      <title>Converting a System Management Facilities (SMF) file to XML (Segment Concatenation)
      </title>
      <titleabbrev>smf</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>segment concatenation</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file field</primary>
        <secondary>packed decimal</secondary>
      </indexterm>
      <indexterm>
        <primary>flat file field</primary>
        <secondary>integer</secondary>
      </indexterm>
      <para>
The example below shows how to convert a System 
Management Facilities (SMF) file to XML.  The example includes support for 
variable
        block spanned (VBS) records. The format of an SMF file is described in
        <ulink url="http://publib.boulder.ibm.com/infocenter/zos/v1r9/index.jsp?topic=/com.ibm.zos.r9.ieag200/smfhdr.htm">SMF records</ulink>.
      </para>

      <para>
The desired output is shown below.
      </para>
      <figure id="smf.xml">
        <title>Output XML file smf.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<smf>
   <smfRecord>
      <systemIndicator>1E</systemIndicator>
      <type>2</type>
   </smfRecord>
   <smfRecord>
      <systemIndicator>DE</systemIndicator>
      <type>110</type>
   </smfRecord>
   <smfRecord>
      <systemIndicator>1E</systemIndicator>
      <type>64</type>
      <jobName>SMF</jobName>
   </smfRecord>
   <smfRecord>
      <systemIndicator>5E</systemIndicator>
      <type>42</type>
      <subType>6</subType>
   </smfRecord>
   <smfRecord>
      <systemIndicator>1E</systemIndicator>
      <type>64</type>
      <jobName>GPL1</jobName>
   </smfRecord>
   <smfRecord>
      <systemIndicator>1E</systemIndicator>
      <type>64</type>
      <jobName>GPL1</jobName>
   </smfRecord>
   <smfRecord>
      <systemIndicator>1E</systemIndicator>
      <type>64</type>
      <jobName>GPL1</jobName>
   </smfRecord>
   <smfRecord>
      <systemIndicator>1E</systemIndicator>
      <type>3</type>
   </smfRecord>
</smf>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-smf.xml">
        <title>Resources script resources-smf.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:xs="http://www.w3.org/2001/XMLSchema"
              xmlns:fn="http://www.w3.org/2005/xpath-functions">

  <sx:service id="smf-xml">
    <sx:serialize>
      <sx:xsltSerializer>
        <sx:outputProperty name="indent" value="yes"/>
      </sx:xsltSerializer>
      <sx:transform>
        <sx:content ref="smf"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="smf">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile ref="smfFile"/>
        <sx:defaultStreamSource encoding="Cp1047"/>
      </sx:flatFileReader>
    </sx:recordStream>
    <sx:recordMapping ref="smfToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="smfFile" lineDelimited="false" countPositionsInBytes="true">
    <sx:flatFileBody>
      <sx:flatRecordType ref="smfType"/>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:vbsFlatRecordType id="smfType">
    <sx:integerField name="recordLength" width="2"/>
    <sx:integerField name="segmentControlCode" width="1"/>
    <sx:integerField name="reserved" width="1"/>
    <sx:mergePhysicalSegments startTest = "number(sx:current//segmentControlCode) = 0 
                                          or number(sx:current//segmentControlCode) = 1"
                             segmentLength="{recordLength}">
      <sx:flatRecordTypeChoice>
        <sx:integerField name="recordLength" width="2"/>
        <sx:integerField name="segmentControlCode" width="1"/>
        <sx:integerField name="reserved" width="1"/>
        <sx:binaryField name="systemIndicator" width="1"/>
        <sx:integerField name="recordType" width="1"/>
        <sx:when test="recordType=64">
          <sx:flatRecordType name="smfType64">
            <sx:integerField name="recordLength" width="2"/>
            <sx:integerField name="segmentControlCode" width="1"/>
            <sx:integerField name="reserved" width="1"/>
            <sx:binaryField name="systemIndicator" label="systemIndicator" width="1"/>
            <sx:integerField name="recordType" label="recordType" width="1"/>
            <sx:positionalField name="jobName" label="Job Name" start="19" width="8"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="recordType=42">
          <sx:flatRecordType name="smfType42">
            <sx:integerField name="recordLength" width="2"/>
            <sx:integerField name="segmentControlCode" width="1"/>
            <sx:integerField name="reserved" width="1"/>
            <sx:binaryField name="systemIndicator" label="systemIndicator" width="1"/>
            <sx:integerField name="recordType" label="recordType" width="1"/>
            <sx:integerField name="subType" label="Sub Type" start="23" width="2"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="recordType=110">
          <sx:flatRecordType name="smfType110">
            <sx:integerField name="recordLength" width="2"/>
            <sx:integerField name="segmentControlCode" width="1"/>
            <sx:integerField name="reserved" width="1"/>
            <sx:binaryField name="systemIndicator" label="systemIndicator" width="1"/>
            <sx:integerField name="recordType" label="recordType" width="1"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:otherwise>
          <sx:flatRecordType name="other">
            <sx:integerField name="recordLength" width="2"/>
            <sx:integerField name="segmentControlCode" width="1"/>
            <sx:integerField name="reserved" width="1"/>
            <sx:binaryField name="systemIndicator" label="systemIndicator" width="1"/>
            <sx:integerField name="recordType" label="recordType" width="1"/>
          </sx:flatRecordType>
        </sx:otherwise>
      </sx:flatRecordTypeChoice>
    </sx:mergePhysicalSegments>
  </sx:vbsFlatRecordType>

  <sx:recordMapping id="smfToXmlMapping">
    <smf>
      <sx:onRecord recordType="smfType64">
        <smfRecord>
          <sx:fieldElementMap field="systemIndicator" element="systemIndicator"/>
          <sx:fieldElementMap field="recordType" element="type"/>
          <sx:fieldElementMap field="jobName" element="jobName"/>
        </smfRecord>
      </sx:onRecord>
      <sx:onRecord recordType="smfType42">
        <smfRecord>
          <sx:fieldElementMap field="systemIndicator" element="systemIndicator"/>
          <sx:fieldElementMap field="recordType" element="type"/>
          <sx:fieldElementMap field="subType" element="subType"/>
        </smfRecord>
      </sx:onRecord>
      <sx:onRecord recordType="smfType110">
        <smfRecord>
          <sx:fieldElementMap field="systemIndicator" element="systemIndicator"/>
          <sx:fieldElementMap field="recordType" element="type"/>
        </smfRecord>
      </sx:onRecord>
      <sx:onRecord recordType="other">
        <smfRecord>
          <sx:fieldElementMap field="systemIndicator" element="systemIndicator"/>
          <sx:fieldElementMap field="recordType" element="type"/>
        </smfRecord>
      </sx:onRecord>
    </smf>
  </sx:recordMapping>

</sx:resources> ]]></programlisting></figure>
      <section>
        <title>Remarks</title>
        <itemizedlist>
          <listitem>
            <para>The field definitions that appear as children of
              <link xlink:href="../guide/index.html#sx:vbsFlatRecordType">sx:vbsFlatRecordType</link>
comprise the 4-byte segment descriptor word (SDW), which describes the segment.
The first 2 bytes contain the length of the segment, including the 4-byte SDW.
The third byte of the SDW contains the segment control code, a value of
              <code>00</code>
indicates that the segment is a complete logical record, and
              <code>01</code>
            indicates that the segment is the first segment of a multisegment
            record.  For more details, see
              <ulink url="http://publib.boulder.ibm.com/infocenter/zvm/v5r3/index.jsp?topic=/com.ibm.zvm.v53.dmsa5/dup0010.htm">segment descriptor word</ulink>.
            </para>
          </listitem>
          <listitem>
            <para>The
              <link xlink:href="../guide/index.html#sx:mergePhysicalSegments">sx:mergePhysicalSegments</link>
            element controls the composition of the mulitple segments into a
            single logical record.  Note that a <sgmltag>segmentControlCode</sgmltag>
               of either 
              <code>00</code> or <code>01</code> marks the beginning of a 
              logical record. By default, the first segment descriptor 
            word goes at the front of the logical record, in the place of a 
            record descriptor word (RDW), 
            subsequent segment descriptor words are discarded.  If the optional
              <sgmltag>suppressRDW</sgmltag> attribute is set to "true", the 
              first segment descriptor word is discarded as well, the SDW fields 
              must be removed from the content of 
                             <link xlink:href="../guide/index.html#sx:mergePhysicalSegments">sx:mergePhysicalSegments</link>, 
              and four bytes need to be subtracted from any positions specified 
              in the record definitions.
            </para>
          </listitem>
          <listitem>
            <para>Note that ServingXML positions are one-based, while the 
              offsets in the IBM documentation are zero-based.
            </para>
          </listitem>
        </itemizedlist>
      </section>

      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-smf.xml -i data/G6744V00.smf -o output/smf.xml smf-xml
]]>
        </programlisting>
      </para>
    </section>

    <section id="recordComposition" xreflabel="recordComposition">
      <title>Aggregating Multiple Physical Records into a Composite Record (Record Composition)
      </title>
      <titleabbrev>record composition</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>record composition</secondary>
      </indexterm>
      <para>
The input file is a fixed field width flat file.
      </para>
      <figure id="composite-records.txt">
        <title>Input flat file composite-records.txt</title>
        <programlisting>
          <![CDATA[
ODANIEL    356996699001 
A233ServingXML132433SAS 
B343443DD2322ARDE021101 
CDANIEL    029299839907    
B344233DD2322PREE021100 
D0000040000002300000001 
A233ServingXML132433AGS 
B3434432323000022021101 
CDANIEL    029299839907 
B3433132323000022021101 
CDANIEL    029299839907 
D0000040000002300000002 
E0030000000100009803600 
]]>
        </programlisting>
      </figure>
      <para>
Note the following properties of this data:
      </para>
      <itemizedlist>
        <listitem>The file begins with an "O" record and ends with an "E" 
          record.
        </listitem>
        <listitem>An "A" record begins a group of records.
        </listitem>
        <listitem>The last three character field of an A record (e.g. "SAS") 
          determines a variant format for a B record.
        </listitem>
      </itemizedlist>
      <para>
The desired output is shown below.
      </para>
      <figure id="composite-records.xml">
        <title>Output XML file composite-records.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<document>
  <header>
    <O>
      <recordType>O</recordType>
      <name>DANIEL</name>
      <id>356</id>
      <code>996699</code>
      <tracking>001</tracking>
    </O>
  </header>
  <body>
    <A>
      <recordType>A</recordType>
      <code>233</code>
      <book>ServingXML</book>
      <isbn>132433</isbn>
      <identifier>SAS</identifier>
    </A>
    <B-SAS>
      <recordType>B</recordType>
      <library>343443</library>
      <shelf>DD2322ARDE</shelf>
      <ebook>021</ebook>
      <code>101</code>
    </B-SAS>
    <C>
      <recordType>C</recordType>
      <author>DANIEL</author>
      <publisher>0292998399</publisher>
      <flag>07</flag>
    </C>
    <B-SAS>
      <recordType>B</recordType>
      <library>344233</library>
      <shelf>DD2322PREE</shelf>
      <ebook>021</ebook>
      <code>100</code>
    </B-SAS>
    <D>
      <recordType>D</recordType>
      <count>000004</count>
      <amount>0000002300</amount>
      <tracking>000001</tracking>
    </D>
    <A>
      <recordType>A</recordType>
      <code>233</code>
      <book>ServingXML</book>
      <isbn>132433</isbn>
      <identifier>AGS</identifier>
    </A>
    <B-AGS>
      <recordType>B</recordType>
      <store>34344323</store>
      <cost>23000022</cost>
      <code>021</code>
      <make>101</make>
    </B-AGS>
    <C>
      <recordType>C</recordType>
      <author>DANIEL</author>
      <publisher>0292998399</publisher>
      <flag>07</flag>
    </C>
    <B-AGS>
      <recordType>B</recordType>
      <store>34331323</store>
      <cost>23000022</cost>
      <code>021</code>
      <make>101</make>
    </B-AGS>
    <C>
      <recordType>C</recordType>
      <author>DANIEL</author>
      <publisher>0292998399</publisher>
      <flag>07</flag>
    </C>
    <D>
      <recordType>D</recordType>
      <count>000004</count>
      <amount>0000002300</amount>
      <tracking>000002</tracking>
    </D>
  </body>
  <trailer>
    <E>
      <recordType>E</recordType>
      <total>00300</total>
      <amount>0000010000</amount>
      <count>9803</count>
      <tracking>600</tracking>
    </E>
  </trailer>
</document>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-recordComposition.xml">
        <title>Resources script resources-recordComposition.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:fn="http://www.w3.org/2005/xpath-functions">

  <sx:service id="composite-records-to-xml">
    <sx:task ref="serialized-composite-records"/>
  </sx:service>

  <sx:serialize id="serialized-composite-records">
    <sx:transform>
      <sx:recordContent ref="composite-record-content"/>
    </sx:transform>
  </sx:serialize>

  <sx:recordContent id="composite-record-content">
    <sx:flatFileReader ref="composite-record-reader"/>
    <sx:recordMapping ref="composite-record-mapping"/>
  </sx:recordContent>

  <sx:flatFileReader id="composite-record-reader">
    <sx:flatFile>
      <sx:flatFileBody>
        <sx:flatRecordTypeChoice>
          <sx:positionalField name="recordType" width="1"/>
          <sx:when test="recordType='O'">
            <sx:flatRecordType ref="O"/>
          </sx:when>
          <sx:when test="recordType='E'">
            <sx:flatRecordType ref="E"/>
          </sx:when>
          <sx:otherwise>
            <sx:compositeFlatRecordType>
              <sx:positionalField name="recordType" width="1"/>
              <sx:positionalField name="code" width="3"/>
              <sx:positionalField name="book" width="10"/>
              <sx:positionalField name="isbn" width="6"/>
              <sx:positionalField name="identifier" width="3"/>
              <sx:combinePhysicalRecords recordType="composite" repeatingGroup="group"
                                    startTest = "sx:current//recordType = 'A' 
                                                 and sx:current//identifier = 'SAS'"
                                    endTest = "sx:current//recordType = 'A'">
                <sx:flatRecordTypeChoice>
                  <sx:positionalField name="recordType" width="1"/>
                  <sx:when test="recordType='A'">
                    <sx:flatRecordType ref="A"/>
                  </sx:when>
                  <sx:when test="recordType='B'">
                    <sx:flatRecordType ref="B-SAS"/>
                  </sx:when>
                  <sx:when test="recordType='C'">
                    <sx:flatRecordType ref="C"/>
                  </sx:when>
                  <sx:when test="recordType='D'">
                    <sx:flatRecordType ref="D"/>
                  </sx:when>
                </sx:flatRecordTypeChoice>
              </sx:combinePhysicalRecords>
              <sx:combinePhysicalRecords recordType="composite" repeatingGroup="group"
                                    startTest = "sx:current//recordType = 'A' 
                                                 and sx:current//identifier = 'AGS'"
                                    endTest = "sx:current//recordType = 'A'">
                <sx:flatRecordTypeChoice>
                  <sx:positionalField name="recordType" width="1"/>
                  <sx:when test="recordType='A'">
                    <sx:flatRecordType ref="A"/>
                  </sx:when>
                  <sx:when test="recordType='B'">
                    <sx:flatRecordType ref="B-AGS"/>
                  </sx:when>
                  <sx:when test="recordType='C'">
                    <sx:flatRecordType ref="C"/>
                  </sx:when>
                  <sx:when test="recordType='D'">
                    <sx:flatRecordType ref="D"/>
                  </sx:when>
                </sx:flatRecordTypeChoice>
              </sx:combinePhysicalRecords>
            </sx:compositeFlatRecordType>
          </sx:otherwise>
        </sx:flatRecordTypeChoice>
      </sx:flatFileBody>
    </sx:flatFile>
  </sx:flatFileReader>

  <sx:flatRecordType id="A" name="A">
    <sx:positionalField name="recordType" width="1"/>
    <sx:positionalField name="code" width="3"/>
    <sx:positionalField name="book" width="10"/>
    <sx:positionalField name="isbn" width="6"/>
    <sx:positionalField name="identifier" width="3"/>
  </sx:flatRecordType>

  <sx:flatRecordType id="C" name="C">
    <sx:positionalField name="recordType" width="1"/>
    <sx:positionalField name="author" width="10"/>
    <sx:positionalField name="publisher" width="10"/>
    <sx:positionalField name="flag" width="2"/>
  </sx:flatRecordType>

  <sx:flatRecordType id="D" name="D">
    <sx:positionalField name="recordType" width="1"/>
    <sx:positionalField name="count" width="6"/>
    <sx:positionalField name="amount" width="10"/>
    <sx:positionalField name="tracking" width="6"/>
  </sx:flatRecordType>

  <sx:flatRecordType id="E" name="E">
    <sx:positionalField name="recordType" width="1"/>
    <sx:positionalField name="total" width="5"/>
    <sx:positionalField name="amount" width="10"/>
    <sx:positionalField name="count" width="4"/>
    <sx:positionalField name="tracking" width="3"/>
  </sx:flatRecordType>

  <sx:flatRecordType id="B-SAS" name="B-SAS">
    <sx:positionalField name="recordType" width="1"/>
    <sx:positionalField name="library" width="6"/>
    <sx:positionalField name="shelf" width="10"/>
    <sx:positionalField name="ebook" width="3"/>
    <sx:positionalField name="code" width="3"/>
  </sx:flatRecordType>
  <sx:flatRecordType id="B-AGS" name="B-AGS">
    <sx:positionalField name="recordType" width="1"/>
    <sx:positionalField name="store" width="8"/>
    <sx:positionalField name="cost" width="8"/>
    <sx:positionalField name="code" width="3"/>
    <sx:positionalField name="make" width="3"/>
  </sx:flatRecordType>

  <sx:flatRecordType id="O" name="O">
    <sx:positionalField name="recordType" width="1"/>
    <sx:positionalField name="name" width="10"/>
    <sx:positionalField name="id" width="3"/>
    <sx:positionalField name="code" width="6"/>
    <sx:positionalField name="tracking" width="3"/>
  </sx:flatRecordType>

  <sx:recordMapping id="composite-record-mapping">
    <document>
      <header>
        <sx:onRecord recordType="O">
          <O>
            <sx:defaultFieldElementMap fields="*"/>
          </O>
        </sx:onRecord>
      </header>
      <body>
        <sx:onRecord recordType="composite">
          <sx:subrecordMapping repeatingGroup="group">
            <sx:onRecord recordType="A">
              <A>
                <sx:defaultFieldElementMap fields="*"/>
              </A>
            </sx:onRecord>
            <sx:onRecord recordType="B-SAS">
              <B-SAS>
                <sx:defaultFieldElementMap fields="*"/>
              </B-SAS>
            </sx:onRecord>
            <sx:onRecord recordType="B-AGS">
              <B-AGS>
                <sx:defaultFieldElementMap fields="*"/>
              </B-AGS>
            </sx:onRecord>
            <sx:onRecord recordType="C">
              <C>
                <sx:defaultFieldElementMap fields="*"/>
              </C>
            </sx:onRecord>
            <sx:onRecord recordType="D">
              <D>
                <sx:defaultFieldElementMap fields="*"/>
              </D>
            </sx:onRecord>
            <sx:onRecord recordType="O">
              <O>
                <sx:defaultFieldElementMap fields="*"/>
              </O>
            </sx:onRecord>
          </sx:subrecordMapping>
        </sx:onRecord>
      </body>
      <trailer>
        <sx:onRecord recordType="E">
          <E>
            <sx:defaultFieldElementMap fields="*"/>
          </E>
        </sx:onRecord>
      </trailer>
    </document>
  </sx:recordMapping>

</sx:resources>
]]></programlisting></figure>
      <section>
        <title>Remarks</title>
        <itemizedlist>
          <listitem>
            <para>The field definitions that appear as children of
              <link xlink:href="../guide/index.html#sx:compositeFlatRecordType">sx:compositeFlatRecordType</link>
              belong to the header of a group of related records.
            </para>
          </listitem>
          <listitem>
            <para>The
              <link xlink:href="../guide/index.html#sx:combinePhysicalRecords">sx:combinePhysicalRecords</link>
            element controls the aggregation of a group of physical records into a
            composite logical record. 
            </para>
          </listitem>
        </itemizedlist>
      </section>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -r resources-recordComposition.xml -i data/composite-records.txt 
    -o output/composite-records.xml composite-records-to-xml
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Computing an Aggregate Value over Multiple Records</title>
      <titleabbrev>aggregates over records</titleabbrev>
      <indexterm>
        <primary>record</primary>
        <secondary>composite</secondary>
      </indexterm>
      <para> This example shows a resources script that will concatenate the values of
  several records into a single XML element value.  It illustrates the use of
  the
        <link xlink:href="../guide/index.html#sx:combineRecords">sx:combineRecords</link>
element.
      </para>
      <para>
The input file is
      </para>
      <figure id="orders.txt">
        <title>Input flat file orders.txt</title>
        <programlisting>
          <![CDATA[
HEADER
ORDER/CUS/CON/USD/
PO1/PAR1/MFR FADD1/5/
REM AAAAA
REM BBBBB
REM CCCCC
PO2/PAR2/MFR 30066/1/
PO3/PAR3/MFR PAGT2/2/
REM CCCCC
REM DDDDD
TRAILER
]]>
        </programlisting>
      </figure>
      <para>
The desired output is
      </para>
      <figure id="order.xml">
        <title>Output XML file order.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Order>
  <OrderHeader>
    <CUS>CUS</CUS>
    <CON>CON</CON>
    <CUR>USD</CUR>
  </OrderHeader>
  <OrderPosition>
    <ORN>PO1</ORN>
    <PAR>PAR1</PAR>
    <QTY>5</QTY>
    <MFR>FADD1</MFR>
    <REM>AAAAA BBBBB CCCCC</REM>
  </OrderPosition>
  <OrderPosition>
    <ORN>PO2</ORN>
    <PAR>PAR2</PAR>
    <QTY>1</QTY>
    <MFR>30066</MFR>
  </OrderPosition>
  <OrderPosition>
    <ORN>PO3</ORN>
    <PAR>PAR3</PAR>
    <QTY>2</QTY>
    <MFR>PAGT2</MFR>
    <REM>CCCCC DDDDD</REM>
  </OrderPosition>
</Order>
]]>
        </programlisting>
      </figure>
      <para>Note that the REM values are concatenated in a space separated list.
      </para>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-order.xml">
        <title>Resources script resources-order.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0"?>
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:fn="http://www.w3.org/2005/xpath-functions">

  <sx:service id="Order">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="Order"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="Order" name="Order">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile ref="OrderFile"/>
      </sx:flatFileReader>
      <sx:combineRecords recordType="composite" repeatingGroup="detail"
                        startTest="sx:current/orderRemarks"
                        endTest="not(sx:current/orderRemarks)">
        <sx:newField name="remarks" select="detail/orderRemarks/REM"/>
      </sx:combineRecords>
    </sx:recordStream>
    <sx:recordMapping ref="OrderToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="OrderFile">
    <sx:commentStarter value="#"/>
    <sx:fieldDelimiter value="/"/>
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:positionalField name="tag" width="3"/>
        <sx:when test="tag='ORD'">
          <sx:flatRecordType name="orderHeader">
            <sx:delimitedField name="CMD" label="Command Code"/>
            <sx:delimitedField name="CUS" label="Customer"/>
            <sx:delimitedField name="CON" label="Contractor"/>
            <sx:delimitedField name="CUR" label="Currency Code"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='REM'">
          <sx:flatRecordType name="orderRemarks">
            <sx:positionalField name="REMTEI" label="Remark" width="3"/>
            <sx:delimitedField name="REM" label="Remark"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='TRA'">
          <sx:flatRecordType name="orderTrailer">
          </sx:flatRecordType>
        </sx:when>
        <sx:otherwise>
          <sx:flatRecordType name="orderPosition">
            <sx:delimitedField name="ORN" label="Order Number"/>
            <sx:delimitedField name="PAR" label="Part Number"/>
            <sx:delimitedField name="MFRTEI" maxWidth="3"/>
            <sx:delimitedField name="MFR" label="Manufacturer"/>
            <sx:delimitedField name="QTY" label="Order Quantity"/>
          </sx:flatRecordType>
        </sx:otherwise>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="OrderToXmlMapping">
    <Order>
      <sx:innerGroup startTest="sx:current/orderHeader">
        <OrderHeader>
          <sx:fieldElementMap field="CUS" element="CUS"/>
          <sx:fieldElementMap field="CON" element="CON"/>
          <sx:fieldElementMap field="CUR" element="CUR"/>
        </OrderHeader>

        <sx:innerGroup startTest="sx:current/orderPosition">
          <OrderPosition>
            <sx:fieldElementMap field="ORN" element="ORN" minOccurs="1"/>
            <sx:fieldElementMap field="PAR" element="PAR"/>
            <sx:fieldElementMap field="QTY" element="QTY"/>
            <sx:fieldElementMap field="MFR" element="MFR" minOccurs="0"/>
            <sx:onRecord recordType="composite">
              <sx:choose>
                <sx:when test="remarks != ''">
                  <sx:fieldElementMap select="remarks" element="REM"/>
                </sx:when>
              </sx:choose>
            </sx:onRecord>
          </OrderPosition>
        </sx:innerGroup>
      </sx:innerGroup>
    </Order>
  </sx:recordMapping>
</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
The effect of
        <link xlink:href="../guide/index.html#sx:combineRecords">sx:combineRecords</link>
is to collect all the
    adjacent
        <sgmltag>orderRemarks</sgmltag>
records, where they become sub-records
    belonging to a field called "detail", and create one record of type
    "composite" that has the repeating group field "detail", plus another field
    "remarks" that is computed from "detail".
      </para>
      <para>
      The
        <sgmltag>orderRemarks</sgmltag>
records flowing into
        <link xlink:href="../guide/index.html#sx:combineRecords">sx:combineRecords</link>
look like, in their
      XML representation,
      </para>
      <programlisting>
        <![CDATA[
<orderRemarks><REMTEI>REM</REMTEI><REM>AAAA</REM></orderRemarks> 
<orderRemarks><REMTEI>REM</REMTEI><REM>BBBB</REM></orderRemarks> 
<orderRemarks><REMTEI>REM</REMTEI><REM>CCCC</REM></orderRemarks> 
]]>
      </programlisting>
      <para>
  The composite record flowing out looks like
      </para>
 

      <programlisting>
        <![CDATA[
<composite> 
  <detail> 
    <orderRemarks><REMTEI>REM</REMTEI><REM>AAAA</REM></orderRemarks> 
    <orderRemarks><REMTEI>REM</REMTEI><REM>BBBB</REM></orderRemarks> 
    <orderRemarks><REMTEI>REM</REMTEI><REM>CCCC</REM></orderRemarks> 
  </detail> 
  <remarks>AAAA BBBB CCCC</remarks> 
</composite> 
]]>
      </programlisting>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i data/order.txt -r resources-order.xml -o output/order.xml Order
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Mapping Two Records at the Top of a File to a Header Element in the
  XML Output</title>
      <titleabbrev>two records to one element</titleabbrev>
      <indexterm>
        <primary>record</primary>
        <secondary>composite</secondary>
      </indexterm>
      <para> This example shows a resources script that maps two records at the top of
  a file to a header element in the XML output.
To map fields from multiple records to the attributes of a single element, you
first need to compose an aggregate of the two records with the
        <link xlink:href="../guide/index.html#sx:combineRecords">sx:combineRecords</link>
instruction.  You
  can then select against the composite record with an
        <link xlink:href="../guide/index.html#sx:fieldAttributeMap">sx:fieldAttributeMap</link>
  and populate the attributes of the parent element.
      </para>
      <para>
The input file is
      </para>
      <figure id="files.txt">
        <title>Input flat file files.txt</title>
        <programlisting>
          <![CDATA[
DP1 458293048kd02 
*****2LV 2008070132 EX9 
E0000015498273 
F0000014938294 
G000001E7839201 
D0000024839305
]]>
        </programlisting>
      </figure>
      <para>The rules for mapping the third through last records are as follows.
      </para>
      <itemizedlist>
        <listitem>
          <para>If a "D" record is found, start a new
            <sgmltag>file</sgmltag>
element, but "D" records are optional.
          </para>
        </listitem>
        <listitem>
          <para>If an "E" record is found, start a new
            <sgmltag>file</sgmltag>
element, unless
         one has already been started because of a
         "D" record.
          </para>
        </listitem>
      </itemizedlist>
      <para>
The desired output is
      </para>
      <figure id="files.xml">
        <title>Output XML file files.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<output date="20080701" sequence="32" 
        code="EX9" reference="458293048kd0">
  <file filenumber="000001"/>
  <file filenumber="000002"/>
</output>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-files.xml">
        <title>Resources script resources-files.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="files">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="filesContent"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="filesContent">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile ref="fileFlatFile"/>
      </sx:flatFileReader>
      <sx:combineRecords recordType="header" repeatingGroup="headerRecords"
                        startTest="sx:current/header1" endTest="sx:previous/header2">
      </sx:combineRecords>
    </sx:recordStream>
    <sx:recordMapping ref="fileToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="fileFlatFile">
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:positionalField name="tag" width="1"/>
        <sx:positionalField name="tag2" width="2"/>
        <sx:when test="tag='D' and tag2='P1'">
          <sx:flatRecordType name="header1">
            <sx:positionalField name="reference" start="5" width="13"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='*'">
          <sx:flatRecordType name="header2">
            <sx:positionalField name="date" start="10" width="8"/>
            <sx:positionalField name="sequence" width="2"/>
            <sx:positionalField name="code" start="21" width="3"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='E'">
          <sx:flatRecordType name="E">
            <sx:positionalField name="filenumber" start="2" width="6"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='D'">
          <sx:flatRecordType name="D">
            <sx:positionalField name="filenumber" start="2" width="6"/>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="fileToXmlMapping">
    <output>
      <sx:fieldAttributeMap select="headerRecords/header2/date" attribute="date"/>
      <sx:fieldAttributeMap select="headerRecords/header2/sequence" attribute="sequence"/>
      <sx:fieldAttributeMap select="headerRecords/header2/code" attribute="code"/>
      <sx:fieldAttributeMap select="headerRecords/header1/reference" attribute="reference"/>
      <sx:groupChoice>
        <sx:innerGroup startTest="sx:current/D" endTest="sx:current/D">
          <file>
            <sx:fieldAttributeMap field="filenumber" attribute="filenumber"/>
          </file>
        </sx:innerGroup>
        <sx:innerGroup startTest="sx:current/E" endTest="sx:current/D or sx:current/E">
          <file>
            <sx:fieldAttributeMap field="filenumber" attribute="filenumber"/>
          </file>
        </sx:innerGroup>
      </sx:groupChoice>
    </output>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
The effect of
        <link xlink:href="../guide/index.html#sx:combineRecords">sx:combineRecords</link>
    is to collect the top two header records,
        <sgmltag>header1</sgmltag>
and
        <sgmltag>header2</sgmltag>
, where they become sub-records belonging to a
    field called "headerRecords", and create one record of type "header" that
    has the repeating group field "headerRecords".
      </para>
      <para>
      The
        <sgmltag>header</sgmltag>
record has the following
      XML representation,
      </para>
      <programlisting>
        <![CDATA[
<header>
  <headerRecords>
    <header1>
      <reference>458293048kd0</reference>
    </header1>
    <header2>
      <date>20080701</date>
      <sequence>32</sequence>
      <code>EX9</code>
    </header2>
  </headerRecords>
</header>
]]>
      </programlisting>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i data/files.txt -r resources-files.xml -o output/files.xml files
]]>
        </programlisting>
      </para>
    </section>
  </section>

  <section>
    <title>Start/End Delimited Records.</title>
    <section>
      <title>Converting flat files with start/end record delimiters (opdef)</title>
      <titleabbrev>opdef</titleabbrev>
      <indexterm>
        <primary>CDATA</primary>
      </indexterm>
      <indexterm>
        <primary>record delimiter</primary>
        <secondary>start/end</secondary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file with start/end record delimiters.
      </para>
      <para>
The input file is shown below.
      </para>
      <figure id="opdef.txt">
        <title>Input file opdef.txt</title>
        <programlisting>
          <![CDATA[
1 20050505 121205 xtyzzya 
{:HJSED 
:20:886452311980706 
:23:CREDDFED 
:32:030612USD5443,99 
:33:USD5443,99 
:50K:GIAN 
NNPLLS 
:52A:B0 
:53A:B33 
:54A:I3N 
:57A:BRE 
:59:/20041010050500001M02606 
KKL S.A 
GNRBBL 
:70:/FF/INV 559661 
:71:SAH 
-} 
3 20050505 121205 bahthy 
]]>
        </programlisting>
      </figure>
      <para>
This file has a number of features.
        <itemizedlist>
          <listitem>
            <para>The first and last lines are header and footers, delimited by new line symbols.
            </para>
          </listitem>
          <listitem>
            <para>The middle part must be taken as a whole chunk, starting from the opening
              <code>{</code>
and ending at the closing
              <code>}</code>
.</para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="opdef.xml">
        <title>Output XML file opdef.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<opdef>
  <start>
    <opdate>20050505</opdate>
    <optime>121205</optime>
    <optarget>xtyzzya</optarget>
  </start>
:HJSED
:20:886452311980706
:23:CREDDFED
:32:030612USD5443,99
:33:USD5443,99
:50K:GIAN
NNPLLS
:52A:B0
:53A:B33
:54A:I3N
:57A:BRE
:59:/20041010050500001M02606
KKL S.A
GNRBBL
:70:/FF/INV 559661
:71:SAH
-
  <end>
    <tpdate>20050505</tpdate>
    <tptime>121205</tptime>
    <tptarget>bahthy</tptarget>
  </end>
</opdef>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-opdef.xml">
        <title>Resources script resources-opdef.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="opdef">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="opdef"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="opdef">
    <sx:flatFileReader>
      <sx:flatFile ref="opdefFlatFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="opdefRecordMapping"/>
  </sx:recordContent>

  <sx:flatFile id="opdefFlatFile" name="opdef">
    <sx:recordDelimiter value="\r\n"/>
    <sx:recordDelimiter value="\n"/>
    <sx:recordDelimiter start="{" end="}"/>
    <sx:flatFileBody trim="true">
      <sx:flatRecordTypeChoice>
        <sx:positionalField name="tag" width="1"/>
        <sx:when test="tag='1'">
          <sx:flatRecordType name="start">
            <sx:positionalField name="tag" width="2"/>
            <sx:positionalField name="opdate" width="9"/>
            <sx:positionalField name="optime" width="7"/>
            <sx:positionalField name="optarget" width="7"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='3'">
          <sx:flatRecordType name="end">
            <sx:positionalField name="tag" width="2"/>
            <sx:positionalField name="tpdate" width="9"/>
            <sx:positionalField name="tptime" width="7"/>
            <sx:positionalField name="tptarget" width="7"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:otherwise>
          <sx:flatRecordType name="data">
            <sx:delimitedField name="field1"/>
          </sx:flatRecordType>
        </sx:otherwise>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="opdefRecordMapping">
    <opdef>
      <sx:onRecord recordType="start">
        <start>
          <sx:defaultFieldElementMap fields="opdate optime optarget"/>
        </start>  
      </sx:onRecord>
      <sx:onRecord recordType="end">
        <end>
          <sx:defaultFieldElementMap fields="tpdate tptime tptarget"/>
        </end>  
      </sx:onRecord>
      <sx:onRecord recordType="data">
        <sx:cdata>
          <sx:toString value="{field1}"/>
        </sx:cdata>
      </sx:onRecord>
    </opdef>
  </sx:recordMapping>  

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points about this script.
        <itemizedlist>
          <listitem>
            <para>
There are three record delimiters, which are checked sequentially.  The third record delimiter specifies both start and end values.
When the start value is found, the matching end value is looked for, taking account of nesting, and the whole returned as one
record.  The chunk returned may contain occurances of the other two delimiters.
            </para>
          </listitem>
          <listitem>
            <para>
The data is mapped to a single field by using a
              <link xlink:href="../guide/index.html#sx:delimitedField">sx:delimitedField</link>
element, taking the default field delimiter, which is the
end of the record.  The data is enclosed in a
              <code>CDATA</code>
section, using the
              <link xlink:href="../guide/index.html#sx:cdata">sx:cdata</link>
element.
            </para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i data/opdef.txt -r resources-opdef.xml 
  -o output/opdef.xml opdef
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Converting flat files with nested start/end record and segment delimiters and name/value pairs (transaction)</title>
      <titleabbrev>transaction</titleabbrev>
      <indexterm>
        <primary>record delimiter</primary>
        <secondary>start/end</secondary>
      </indexterm>
      <indexterm>
        <primary>field</primary>
tagged</indexterm>
      <indexterm>
        <primary>repeating segment</primary>
      </indexterm>
      <para>
The example below shows how to convert a
flat file with nested start/end record and segment delimiters and name/value pairs.
      </para>
      <para>
The input file is shown below.
      </para>
      <figure id="transaction.txt">
        <title>Input file transaction.txt</title>
        <programlisting>
          <![CDATA[
{TRAN:trantype=PRIN#origin=Toronto#
{TRANREF:reftype=TREF#ref=1234567890123456B#}
{TRANREF:reftype=FOTR#ref=1234567890123456#}
{DRIVER:drivertype=OPER#drivercode=SELL#}
{DRIVER:drivertype=STRM#drivercode=FOP#}
{INSTR:instrtype=PINS#instrreftype=INT#instrref=PTEQTY1#qty=1000000#}
{INSTR:instrtype=TCCY#instrreftype=ISO#instrref=USD#}
{INSTR:instrtype=SINS#instrreftype=ISO#instrref=USD#}
{PARTY:partytype=COMP#partyreftype=X3#partyref=CMP1#}
{PARTY:partytype=SECP#partyreftype=X3#partyref=PTSECP1#}
{DATE:datetype=TDAT#date=01-Jan-2007#}
{DATE:datetype=VDAT#date=01-Jan-2007#}
{CHARGE:chargetype=COMM#calctype=NONE#chargeamount=50.00#instrreftype=ISO#instrref=USD}
{PRICE:ratetype=TPRC#price=4.9#multdiv=X1#pricetype=YP#}
}
]]>
        </programlisting>
      </figure>
      <para>
This file has a number of features.
        <itemizedlist>
          <listitem>
            <para>The entire record is contained inside "{" - "}" record delimiters.
            </para>
          </listitem>
          <listitem>
            <para>The first field in the record is delimited by a ":" and identifies the type of the record.
            </para>
          </listitem>
          <listitem>
            <para>The record contains a number of name/value pairs, with names and values separated
by the character "=", and fields terminated by the character "#".
            </para>
          </listitem>
          <listitem>
            <para>The record contains a number of segments enclosed in "{" - "}" segment delimiters.
            </para>
          </listitem>
          <listitem>
            <para>The first field in each segment is delimited by a ":" and identifies the type of the segment.
            </para>
          </listitem>
          <listitem>
            <para>Each segment contains a number of name/value pairs, with names and values separated
by the character "=", and fields terminated by the character "#".
            </para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
The desired output is shown below.
      </para>
      <figure id="transaction.xml">
        <title>Output XML file transaction.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<transaction>
  <TRAN>
    <record-type>TRAN</record-type>
    <trantype>PRIN</trantype>
    <origin>Toronto</origin>
    <segments>
      <TRANREF>
        <record-type>TRANREF</record-type>
        <reftype>TREF</reftype>
        <ref>1234567890123456B</ref>
      </TRANREF>
      <TRANREF>
        <record-type>TRANREF</record-type>
        <reftype>FOTR</reftype>
        <ref>1234567890123456</ref>
      </TRANREF>
      <DRIVER>
        <record-type>DRIVER</record-type>
        <drivertype>OPER</drivertype>
        <drivercode>SELL</drivercode>
      </DRIVER>
      <DRIVER>
        <record-type>DRIVER</record-type>
        <drivertype>STRM</drivertype>
        <drivercode>FOP</drivercode>
      </DRIVER>
      <INSTR>
        <record-type>INSTR</record-type>
        <instrtype>PINS</instrtype>
        <instrreftype>INT</instrreftype>
        <instrref>PTEQTY1</instrref>
        <qty>1000000</qty>
      </INSTR>
      <INSTR>
        <record-type>INSTR</record-type>
        <instrtype>TCCY</instrtype>
        <instrreftype>ISO</instrreftype>
        <instrref>USD</instrref>
      </INSTR>
      <INSTR>
        <record-type>INSTR</record-type>
        <instrtype>SINS</instrtype>
        <instrreftype>ISO</instrreftype>
        <instrref>USD</instrref>
      </INSTR>
      <PARTY>
        <record-type>PARTY</record-type>
        <partytype>COMP</partytype>
        <partyreftype>X3</partyreftype>
        <partyref>CMP1</partyref>
      </PARTY>
      <PARTY>
        <record-type>PARTY</record-type>
        <partytype>SECP</partytype>
        <partyreftype>X3</partyreftype>
        <partyref>PTSECP1</partyref>
      </PARTY>
      <DATE>
        <record-type>DATE</record-type>
        <datetype>TDAT</datetype>
        <date>01-Jan-2007</date>
      </DATE>
      <DATE>
        <record-type>DATE</record-type>
        <datetype>VDAT</datetype>
        <date>01-Jan-2007</date>
      </DATE>
      <CHARGE>
        <record-type>CHARGE</record-type>
        <chargetype>COMM</chargetype>
        <calctype>NONE</calctype>
        <chargeamount>50.00</chargeamount>
        <instrreftype>ISO</instrreftype>
        <instrref>USD</instrref>
      </CHARGE>
      <PRICE>
        <record-type>PRICE</record-type>
        <ratetype>TPRC</ratetype>
        <price>4.9</price>
        <multdiv>X1</multdiv>
        <pricetype>YP</pricetype>
      </PRICE>
    </segments>
  </TRAN>
</transaction>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-transaction.xml">
        <title>Resources script resources-transaction.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="transaction">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="transaction-content"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="transaction-content" name="transaction">
    <sx:flatFileReader>
      <sx:flatFile ref="transaction-flat-file"/>
    </sx:flatFileReader>
  </sx:recordContent>

  <sx:flatFile id="transaction-flat-file">
    <sx:recordDelimiter start="{" end="}"/>
    <sx:flatFileBody>
      <sx:repeatDelimiter start="{" end="}"/>
      <sx:nameDelimiter value="="/>
      <sx:flatRecordType name="TRAN">
        <sx:delimitedField name="record-type">
          <sx:fieldDelimiter value=":"/>
        </sx:delimitedField>
        <sx:repeatingField>
          <sx:fieldDelimiter value="#"/>
          <sx:segmentDelimiter value="{"/> 
          <sx:delimitedNamedField/>
        </sx:repeatingField>
        <sx:repeatingGroup name="segments">
          <sx:flatRecordTypeChoice>
            <sx:delimitedField name="record-type">
              <sx:fieldDelimiter value=":"/>
            </sx:delimitedField>
            <sx:when test="1=1">
              <sx:flatRecordType name="{record-type}">
                <sx:delimitedField name="record-type">
                  <sx:fieldDelimiter value=":"/>
                </sx:delimitedField>
                <sx:repeatingField> 
                  <sx:delimitedNamedField/>
                  <sx:fieldDelimiter value="#"/>
                </sx:repeatingField>
              </sx:flatRecordType>
            </sx:when>
          </sx:flatRecordTypeChoice>
        </sx:repeatingGroup>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points about this script.
        <itemizedlist>
          <listitem>
            <para>
The value of the first field in the segment, terminated by ":", is assigned as the record type name of the segment.
            </para>
          </listitem>
          <listitem>
            <para>
All the name/value pairs within a segment are read with a single
              <link xlink:href="../guide/index.html#sx:repeatingField">sx:repeatingField</link>
element.
            </para>
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i data/transaction.txt -r resources-transaction.xml 
  -o output/transaction.xml transaction
]]>
        </programlisting>
      </para>
    </section>
  </section>

  <section>
    <title>Custom Record Reader</title>
    <section id="custom_record_reader" xreflabel="custom_record_reader">
      <title>Converting the output of a custom record reader to XML (custom record reader)</title>
      <titleabbrev>custom record reader</titleabbrev>
      <indexterm>
        <primary>record reader</primary>
        <secondary>custom</secondary>
      </indexterm>
      <para>
The example below shows how to convert the
the output of a custom record reader to XML.
      </para>
      <para>
The input records are generated by the following Java class.
      </para>
      <figure id="TradeRecordReader.java">
        <title>TradeRecordReader Java class</title>
        <programlisting>
          <![CDATA[
package flat2xml;

import com.servingxml.app.ServiceContext;
import com.servingxml.components.recordio.AbstractRecordReader;
import com.servingxml.app.Flow;
import com.servingxml.util.Name;
import com.servingxml.util.QualifiedName;
import com.servingxml.util.ServingXmlException;
import com.servingxml.util.record.Record;
import com.servingxml.util.record.RecordBuilder;

public class TradeRecordReader extends AbstractRecordReader {
  private static final Name TRADE_RECORD_TYPE = new QualifiedName("trade");
  private static final Name TRANSACTION_RECORD_TYPE = new QualifiedName("transaction");
  private static final Name RECORD_TYPE_NAME = new QualifiedName("record_type");
  private static final Name ID_NAME = new QualifiedName("id");
  private static final Name TRADE_DATE_NAME = new QualifiedName("trade_date");
  private static final Name TRADE_TIME_NAME = new QualifiedName("trade_time");
  private static final Name DESCRIPTION_NAME = new QualifiedName("description");
  private static final Name REFERENCE_NAME = new QualifiedName("reference");
  
  public void readRecords(ServiceContext context, Flow flow) 
   {

    //  Start the record stream
    startRecordStream(context, flow);

    RecordBuilder trRecordBuilder = new RecordBuilder(TRADE_RECORD_TYPE);
    RecordBuilder tnRecordBuilder = new RecordBuilder(TRANSACTION_RECORD_TYPE);

    Record record;

    trRecordBuilder.setString(RECORD_TYPE_NAME,"TR");
    trRecordBuilder.setString(ID_NAME,"0001");
    trRecordBuilder.setString(TRADE_DATE_NAME,"03/25/2005");
    trRecordBuilder.setString(TRADE_TIME_NAME,"01:50:00");
    trRecordBuilder.setString(DESCRIPTION_NAME,"This is a trade record");
    record = trRecordBuilder.toRecord();
    trRecordBuilder.clear();

    //  Write the "trade" record
    writeRecord(context, flow, record);

    tnRecordBuilder.setString(RECORD_TYPE_NAME,"TN");
    tnRecordBuilder.setString(ID_NAME,"0002");
    tnRecordBuilder.setString(REFERENCE_NAME,"X1234");
    tnRecordBuilder.setString(DESCRIPTION_NAME,"A child transaction");
    record = tnRecordBuilder.toRecord();   
    tnRecordBuilder.clear();

    //  Write the first "transaction" record
    writeRecord(context, flow, record);

    tnRecordBuilder.setString(RECORD_TYPE_NAME,"TN");
    tnRecordBuilder.setString(ID_NAME,"0003");
    tnRecordBuilder.setString(REFERENCE_NAME,"X1235");
    tnRecordBuilder.setString(DESCRIPTION_NAME,"Another child transaction");
    record = tnRecordBuilder.toRecord();
    tnRecordBuilder.clear();

    //  Write the second "transaction" record
    writeRecord(context, flow, record);

    //  End the record stream
    endRecordStream(context, flow);
  }
}
]]>
        </programlisting>
      </figure>
      <para>The
        <code>TradeRecordReader</code>
class will generate the following stream of records.
      </para>
      <informaltable colsep="0">
        <tgroup cols="4" align="left" colsep="0" rowsep="1">
          <thead>
            <row>
              <entry>record_type</entry>
              <entry>id</entry>
              <entry>trade_date</entry>
              <entry>trade_time</entry>
              <entry>description</entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry>TR</entry>
              <entry>0001</entry>
              <entry>03/25/2005</entry>
              <entry> 1:50:00</entry>
              <entry>This is a trade record</entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
      <para/>
      <informaltable colsep="0">
        <tgroup cols="4" align="left" colsep="0" rowsep="1">
          <thead>
            <row>
              <entry>record_type</entry>
              <entry>id</entry>
              <entry>reference</entry>
              <entry>description</entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry>TN</entry>
              <entry>0002</entry>
              <entry>X1234</entry>
              <entry>A child transaction</entry>
            </row>
            <row>
              <entry>TN</entry>
              <entry>0003</entry>
              <entry>X1235</entry>
              <entry>Another child transaction</entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>

      <para>
The desired output is the same as for the trades example.
      </para>
      <figure id="custom_trade_reader_trades.xmll">
        <title>Output XML file trades.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<trades feed="LONDON">
  <trade id="0001">
    <trade-date>2005-03-25T01:50:00.000-05:00</trade-date>
    <description>This is a trade record</description>
  </trade>
  <transaction id="0002">
    <reference>X1234</reference>
    <description>A child transaction</description>
  </transaction>
  <transaction id="0003">
    <reference>X1235</reference>
    <description>Another child transaction</description>
  </transaction>
</trades>
]]>
        </programlisting>
      </figure>
      <para>
The following resources script does the transformation.
      </para>
      <figure id="resources-custom_trade_reader.xml">
        <title>Resources script resources-custom_trade_reader.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="trades">
    <sx:parameter name="feed">
      <sx:defaultValue>NY</sx:defaultValue>
    </sx:parameter>
    <sx:serialize>
      <sx:transform>
        <sx:content ref="trades"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="trades">
    <sx:customRecordReader class="flat2xml.TradeRecordReader"/>
    <sx:recordMapping ref="tradesToXmlMapping"/>
  </sx:recordContent>

  <sx:recordMapping id="tradesToXmlMapping">
    <trades>
      <sx:fieldAttributeMap value="{$feed}" attribute="feed"/>
      <sx:onRecord recordType="trade">
        <trade>
          <sx:fieldAttributeMap field="id" attribute="id"/>
          <sx:elementMap element="trade-date">
            <sx:convertToDateTime format="MM/dd/yyyy H:mm:ss">
              <sx:concat separator=" ">
                <sx:toString value="{trade_date}"/>
                <sx:toString value="{trade_time}"/>
              </sx:concat>
            </sx:convertToDateTime>
          </sx:elementMap>
          <sx:fieldElementMap field="description" element="description"/>
        </trade>
      </sx:onRecord>
      <sx:onRecord recordType="transaction">
        <transaction>
          <sx:fieldAttributeMap field="id" attribute="id"/>
          <sx:fieldElementMap field="reference" element="reference"/>
          <sx:fieldElementMap field="description" element="description"/>
        </transaction>
      </sx:onRecord>
    </trades>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
Note the following points.
        <itemizedlist>
          <listitem>
The record content is defined by a custom record reader, implemented in the Java class
            <code>TradeRecordReader</code>
.
          </listitem>
        </itemizedlist>
      </para>
      <para>
You can run this example on the command line by
        <itemizedlist>
          <listitem>
Compiling the Java class
            <code>TradeRecordReader</code>
and copying
the resulting
            <filename>.class</filename>
file into the
            <filename>dir/classes</filename>
directory
          </listitem>
          <listitem>
Entering the command
            <programlisting>
              <![CDATA[
servingxml -r resources-custom_trade_reader.xml
  -o output/trades.xml trades feed=LONDON
]]>
            </programlisting>
          </listitem>
        </itemizedlist>
      </para>
    </section>
  </section>

  <section>
    <title>Batching XML Output</title>
    <section>
      <title>Serializing XML in Batches</title>
      <titleabbrev>serializing batches</titleabbrev>
      <indexterm>
        <primary>batch</primary>
        <secondary>XML</secondary>
      </indexterm>
      <para>This example shows how to 
serialize an XML document in batches.  It illustrates the use of
  the
        <link xlink:href="../guide/index.html#sx:batchedSerializer">sx:batchedSerializer</link>
        element.
      </para>
      <para>Suppose you want to read the CSV file countries.csv and serialize it to
  XML, but you also want the following:
      </para>
      <itemizedlist>
        <listitem>
          <para>Country subtrees to be split over multiple documents, no
                more than 50 to any one file.
          </para>
          <programlisting>
            <![CDATA[
          06/12/2007  07:37 PM    <DIR>          .
          06/12/2007  07:37 PM    <DIR>          ..
          06/12/2007  07:37 PM             3,773 countries-1.xml
          06/12/2007  07:37 PM             3,758 countries-2.xml
          06/12/2007  07:37 PM             3,747 countries-3.xml
          06/12/2007  07:37 PM             3,753 countries-4.xml
          06/12/2007  07:37 PM             3,416 countries-5.xml
          ]]>
          </programlisting>

        </listitem>
        <listitem>
          <para>Each document to begin with all the XML nodes up to the
                  occurance of the first country subtree.
          </para>
        </listitem>
      </itemizedlist>

      <para>
The following resources script produces the desired output.
      </para>
      <programlisting>
        <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:msv="http://www.servingxml.com/extensions/msv">

  <sx:service id="countries">
    <sx:serialize>
      <sx:transform>
        <sx:content ref="countries"/>
      </sx:transform>
      <sx:batchedSerializer path="country" batchSize="50">
        <sx:xsltSerializer>
          <sx:fileSink file="output/countries-{$sx:batchSequenceNumber}.xml"/>
        </sx:xsltSerializer>
      </sx:batchedSerializer>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="countries" name="countries">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:urlSource url="data/countries.csv"/>
        <sx:flatFile ref="countriesFile"/>
      </sx:flatFileReader>
      <msv:recordValidator>
        <sx:urlSource url="data/country-record.xsd"/>
      </msv:recordValidator>
      <sx:discardHandler>
        <sx:log message="{$sx:message}"/>
      </sx:discardHandler>
    </sx:recordStream>
    <sx:recordMapping ref="countriesToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="countriesFile">
    <sx:commentStarter value="#"/>
    <sx:flatFileHeader lineCount="1"/>
    <sx:flatFileBody>
      <sx:flatRecordType name="country">
        <sx:fieldDelimiter value=","/>
        <sx:delimitedField name="code"/>
        <sx:delimitedField name="name" trimLeading="true"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="countriesToXmlMapping">
    <countries>
      <sx:onRecord>
        <country>
          <sx:fieldElementMap field="name" element="countryName"/>
          <sx:fieldAttributeMap field="code" attribute="countryCode"/>
        </country>
      </sx:onRecord>
    </countries>
  </sx:recordMapping>

</sx:resources>
]]>
      </programlisting>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml  -r resources-batches.xml countries 
  rootName=countries
]]>
        </programlisting>
      </para>
    </section>
    <section>
      <title>Writing Records to Batch Files, and Converting the Batches to Separate
  XML Files
      </title>
      <titleabbrev>batched XML</titleabbrev>
      <indexterm>
        <primary>batch</primary>
        <secondary>records</secondary>
      </indexterm>
      <indexterm>
        <primary>batch</primary>
        <secondary>XML</secondary>
      </indexterm>
      <para>
The example illustrates an alternative way of producing XML in batches, in two
steps:
      </para>
      <itemizedlist>
        <listitem>
          <para>First, split a large flat file into a number of smaller
                  flat files.
          </para>
        </listitem>
        <listitem>
          <para>Second, convert each of the smaller flat files to XML.
          </para>
        </listitem>
      </itemizedlist>
      <para>Suppose you want to convert the countries.csv file containing 245 country
records to XML, each country record mapped to one country subtree, and the
output spilt over multiple XML files.
      </para>
      <para>
The first step is to produce the batched csv files and output them to an
intermediate directory.
      </para>
      <figure id="countries-d.csv">
        <title>Batched intermediate CSV files.</title>
        <programlisting>
          <![CDATA[
06/12/2007  07:24 PM    <DIR>          .
06/12/2007  07:24 PM    <DIR>          ..
06/12/2007  07:24 PM               814 countries-1.csv
06/12/2007  07:24 PM               795 countries-2.csv
06/12/2007  07:24 PM               786 countries-3.csv
06/12/2007  07:24 PM               784 countries-4.csv
06/12/2007  07:24 PM               793 countries-5.csv
]]>
        </programlisting>
      </figure>
      <para>
The second step is to read all the csv files in the intermediate directory and serialize them to XML.
      </para>

      <figure id="countries-d.xml">
        <title>Batched XML files.</title>
        <programlisting>
          <![CDATA[
06/12/2007  07:37 PM    <DIR>          .
06/12/2007  07:37 PM    <DIR>          ..
06/12/2007  07:37 PM             3,773 countries-1.xml
06/12/2007  07:37 PM             3,758 countries-2.xml
06/12/2007  07:37 PM             3,747 countries-3.xml
06/12/2007  07:37 PM             3,753 countries-4.xml
06/12/2007  07:37 PM             3,416 countries-5.xml
]]>
        </programlisting>
      </figure>
      <para>
The following resources script performs both steps.
      </para>
      <programlisting>
        <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:service id="countries">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:fileSource file="data/{$rootName}.csv"/>
        <sx:flatFile ref="countriesFile"/>
      </sx:flatFileReader>
      <sx:batchedRecordWriter batchSize="50">
        <sx:flatFileWriter>
          <sx:fileSink file="intermediate/{$rootName}-{$sx:batchSequenceNumber}.csv"/>
          <sx:flatFile ref="countriesFile"/>
        </sx:flatFileWriter>
      </sx:batchedRecordWriter>
    </sx:recordStream>

    <sx:recordStream>
      <sx:directoryReader directory="intermediate">
        <sx:fileFilter pattern="countries.*[.]csv"/>
      </sx:directoryReader>
      <sx:processRecord>
        <sx:parameter name="output-file">
          <sx:findAndReplace searchFor ="(countries.*)[.]csv" replaceWith ="$1.xml">
            <sx:toString value="{name}"/>
          </sx:findAndReplace>
        </sx:parameter>
        <sx:serialize>
          <sx:xsltSerializer>
            <sx:fileSink directory="output" file="{$output-file}"/>
          </sx:xsltSerializer>
          <sx:transform>
            <sx:content ref="countries"/>
          </sx:transform>
        </sx:serialize>
      </sx:processRecord>
    </sx:recordStream>
  </sx:service>

  <sx:recordContent id="countries">
    <sx:flatFileReader>
      <sx:fileSource directory="{parentDirectory}" file="{name}"/>
      <sx:flatFile ref="countriesFile"/>
    </sx:flatFileReader>
    <sx:recordMapping ref="countriesToXmlMapping"/>
  </sx:recordContent>

  <sx:flatFile id="countriesFile">
    <sx:commentStarter value="#"/>
    <sx:flatFileBody>
      <sx:flatRecordType name="country">
        <sx:fieldDelimiter value=","/>
        <sx:delimitedField name="code"/>
        <sx:delimitedField name="name" trimLeading="true"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="countriesToXmlMapping">
    <countries>
      <sx:onRecord>
        <country>
          <sx:fieldElementMap field="name" element="countryName"/>
          <sx:fieldAttributeMap field="code" attribute="countryCode"/>
        </country>
      </sx:onRecord>
    </countries>
  </sx:recordMapping>

</sx:resources>
]]>
      </programlisting>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml  -r resources-batchRecords.xml countries 
  rootName=countries
]]>
        </programlisting>
      </para>
    </section>
  </section>

  <section>
    <title>Many XML Documents</title>
    <section>
      <title>Flat File to Summary and Detail XML Documents (eobclaims)</title>
      <titleabbrev>eobclaims to XMLs</titleabbrev>
      <indexterm>
        <primary>XML output</primary>
        <secondary>multiple documents</secondary>
      </indexterm>
      <para> This example requires reading the flat file
      </para>
      <programlisting>
        <![CDATA[
  ADM2301EOBS
  HDR06/13/08200815501300101MEMBER01          BISHOP         
  ADR1234 TEST DR                                                                                       ARVADA            
  HDR06/13/08200815501300102MEMBER02          BISHOP         
  ADR5678 TEST DR                                                                                       ARVADA            
  TLRTOTAL EOBS GENERATED: 0000001000000000000010000018                                                                                                                                                                                                                                                       
  ]]>
      </programlisting>
      <para>and producing this output:
      </para>
      <itemizedlist>
        <listitem>
          <para>One summary XML document capturing the header ("ADM") and
        trailer ("TLR") records
          </para>
          <programlisting>
            <filename>eobinputoutput.xml</filename>
          </programlisting>
        </listitem>
        <listitem>
          <para>Separate XML documents for each pair of "HDR" and "ADR"
                records
          </para>
          <programlisting>
            <filename>eobinputoutput-061308200815501300101.xml</filename>
            <filename>eobinputoutput-061308200815501300102.xml</filename>
          </programlisting>
        </listitem>
      </itemizedlist>
      <para>The summary XML document is to look like
      </para>
      <programlisting>
        <![CDATA[
  <?xml version="1.0" encoding="UTF-8"?>
  <eobs>
     <ADMIN_RECTYPE record_type="ADM">
        <ADM_0001_TEXT>2301EOBS</ADM_0001_TEXT>
     </ADMIN_RECTYPE>
     <TLR-REC-TYPE record_type="TLR">
        <TLR_0001_TEXT>TOTAL EOBS GENERATED: 0</TLR_0001_TEXT>
        <TLR_0001_COUNT>0000010</TLR_0001_COUNT>
        <FILLER>00000000000010000018</FILLER>
     </TLR-REC-TYPE>
  </eobs>
  ]]>
      </programlisting>
      <para>and the first detail documents as
      </para>
      <programlisting>
        <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<eob>
   <HEADER_RECTYPE record_type="HDR">
      <HDR_STMT_DATE>06/13/08</HDR_STMT_DATE>
      <HDR_CLAIM_NUMBER>200815501300101</HDR_CLAIM_NUMBER>
      <HDR_PATIENT_NAME_FIRST>MEMBER01</HDR_PATIENT_NAME_FIRST>
      <HDR_PATIENT_NAME_MIDDLE/>
      <HDR_PATIENT_NAME_LAST>BISHOP</HDR_PATIENT_NAME_LAST>
   </HEADER_RECTYPE>
   <ADR_REC_TYPE record_type="ADR">
      <ADR_8512_ATTN>1234 TEST DR</ADR_8512_ATTN>
      <ADR_8513_STREET1/>
      <ADR_8513_STREET2/>
      <ADR_8514_CITY>ARVADA</ADR_8514_CITY>
   </ADR_REC_TYPE>
</eob>
  ]]>
      </programlisting>
      <para>Below is the required resources script.  Since the structure of the
    record input will be shared with another example, we'll collect that in a
    separate script and include it in the main one.
      </para>
      <figure id="resource-eobclaims-flatfile.xml" xreflabel="eobclaims record structure declarations">
        <title>Record structure resource-eobclaims-flatfile.xml</title>
        <programlisting>
          <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:flatFile id="eobclaims-file">
    <sx:flatFileBody>
      <sx:flatRecordType ref="eobclaims-record"/>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:flatRecordTypeChoice id="eobclaims-record">
    <sx:positionalField name="record_type" width="3"/>
    <sx:when test="record_type='ADM'">
      <sx:flatRecordType ref="adm"/>
    </sx:when>
    <sx:when test="record_type='HDR'">
      <sx:flatRecordType ref="hdr"/>
    </sx:when>
    <sx:when test="record_type='ADR'">
      <sx:flatRecordType ref="adr"/>
    </sx:when>
    <sx:when test="record_type='TLR'">
      <sx:flatRecordType ref="tlr"/>
    </sx:when>
  </sx:flatRecordTypeChoice>

  <sx:flatRecordType id="adm" name="ADM">
    <sx:positionalField name="record_type" width="3"/>
    <sx:positionalField name="ADM_0001_TEXT" width="20"/>
    <sx:positionalField name="ADM_0001_RUN_DATE" width="249"/>
    <sx:positionalField name="FILLER" width="8"/>
  </sx:flatRecordType>

  <sx:flatRecordType id="tlr" name="TLR">
    <sx:positionalField name="record_type" width="3"/>
    <sx:positionalField name="TLR_0001_TEXT" width="23"/>
    <sx:positionalField name="TLR_0001_COUNT" width="7"/>
    <sx:positionalField name="FILLER" width="268"/>
  </sx:flatRecordType>

  <sx:flatRecordType id="hdr" name="HDR">
    <sx:positionalField name="record_type" width="3"/>
    <sx:positionalField name="HDR_STMT_DATE" width="8"/>
    <sx:positionalField name="HDR_CLAIM_NUMBER" width="15"/>
    <sx:positionalField name="HDR_PATIENT_NAME_FIRST" width="18"/>
    <sx:positionalField name="HDR_PATIENT_NAME_LAST" width="15"/>
  </sx:flatRecordType>

  <sx:flatRecordType id="adr" name="ADR">
    <sx:positionalField name="record_type" width="3"/>
    <sx:positionalField name="ADR_8512_ATTN" width="99"/>
    <sx:positionalField name="ADR_8514_CITY" start="103" width="18"/>
  </sx:flatRecordType>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <figure id="resource-eobclaims.xml">
        <title>Main resources script resource-eobclaims.xml</title>
        <programlisting>
          <![CDATA[
<?xml version="1.0"?>

<sx:resources xmlns:sx="http://www.servingxml.com/core">

  <sx:include href="resources-eobclaims-flatfile.xml"/>

  <sx:service id="eobclaims-to-xml">
    <!-- Do the header/trailer first -->
    <sx:serialize>
      <sx:xsltSerializer>
        <sx:fileSink directory="output" file="eobinputoutput.xml"/>
        <sx:outputProperty name="indent" value="yes"/>
      </sx:xsltSerializer>
      <sx:transform>
        <sx:recordContent>
          <sx:flatFileReader>
            <sx:flatFile ref="eobclaims-file"/>
          </sx:flatFileReader>
          <sx:recordMapping ref="eobclaims-header-trailer-mapping"/>
        </sx:recordContent>
      </sx:transform>
    </sx:serialize>

    <!-- Now do the body -->
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile ref="eobclaims-file"/>
      </sx:flatFileReader>
      <!-- Compose a composite record out of each HDR-ADR pair -->
      <sx:combineRecords recordType="composite" repeatingGroup="eob"
                  startTest="sx:current/HDR"
                  endTest="sx:previous/ADR">
        <sx:newField name="HDR_STMT_DATE" select="eob/HDR/HDR_STMT_DATE"/>
        <sx:newField name="HDR_CLAIM_NUMBER" select="eob/HDR/HDR_CLAIM_NUMBER"/>
      </sx:combineRecords>
      <!-- Discard the records that are not HDR-ADR pairs -->
      <sx:restrictRecordFilter>
        <sx:recordRestriction recordType="composite"/>
      </sx:restrictRecordFilter>
      <!-- Process each HDR-ADR composite record -->
      <sx:processRecord>
        <!-- Construct and store the output filename in the parameter "output-file" -->
        <sx:parameter name="output-file">
          <sx:findAndReplace searchFor="/" replaceWith ="">
            <sx:toString value="eobinputoutput-{HDR_STMT_DATE}{HDR_CLAIM_NUMBER}.xml"/>
          </sx:findAndReplace>
        </sx:parameter>

        <sx:serialize>
          <sx:xsltSerializer>
            <sx:fileSink directory="output" file="{$output-file}"/>
            <sx:outputProperty name="indent" value="yes"/>
          </sx:xsltSerializer>
          <sx:transform>
            <sx:recordContent>
              <sx:recordMapping ref="eobclaims-body-mapping"/>
            </sx:recordContent>
          </sx:transform>
        </sx:serialize>
      </sx:processRecord>
    </sx:recordStream>
  </sx:service>

  <sx:recordMapping id="eobclaims-header-trailer-mapping">
    <eobs>
      <sx:onRecord recordType="ADM">
        <ADMIN_RECTYPE record_type="ADM">
          <sx:fieldElementMap field="ADM_0001_TEXT" element="ADM_0001_TEXT"/>
        </ADMIN_RECTYPE>
      </sx:onRecord>
      <sx:onRecord recordType="TLR">
        <TLR-REC-TYPE record_type="TLR">
          <sx:fieldElementMap field="TLR_0001_TEXT" element="TLR_0001_TEXT"/>
          <sx:fieldElementMap field="TLR_0001_COUNT" element="TLR_0001_COUNT"/>
          <sx:fieldElementMap field="FILLER" element="FILLER"/>
        </TLR-REC-TYPE>
      </sx:onRecord>
    </eobs>
  </sx:recordMapping>

  <sx:recordMapping id="eobclaims-body-mapping">
    <eob>
      <!-- Our composite record has a repeating group field, "eob", 
           that has two sub-records, "HDR" and "ADR" -->
      <sx:onRecord recordType="composite">
        <sx:subrecordMapping repeatingGroup="eob">
          <sx:onRecord recordType="HDR">
            <HEADER_RECTYPE>
              <sx:fieldAttributeMap field="record_type" attribute="record_type"/>
              <sx:fieldElementMap field="HDR_STMT_DATE" element="HDR_STMT_DATE"/>
              <sx:fieldElementMap field="HDR_CLAIM_NUMBER" element="HDR_CLAIM_NUMBER"/>
              <sx:fieldElementMap field="HDR_PATIENT_NAME_FIRST" element="HDR_PATIENT_NAME_FIRST"/>
              <sx:fieldElementMap field="HDR_PATIENT_NAME_MIDDLE" element="HDR_PATIENT_NAME_MIDDLE"/>
              <sx:fieldElementMap field="HDR_PATIENT_NAME_LAST" element="HDR_PATIENT_NAME_LAST"/>
            </HEADER_RECTYPE>
          </sx:onRecord>
          <sx:onRecord recordType="ADR">
            <ADR_REC_TYPE>
              <sx:fieldAttributeMap field="record_type" attribute="record_type"/>
              <sx:fieldElementMap field="ADR_8512_ATTN" element="ADR_8512_ATTN"/>
              <sx:fieldElementMap field="ADR_8513_STREET1" element="ADR_8513_STREET1"/>
              <sx:fieldElementMap field="ADR_8513_STREET2" element="ADR_8513_STREET2"/>
              <sx:fieldElementMap field="ADR_8514_CITY" element="ADR_8514_CITY"/>
            </ADR_REC_TYPE>
          </sx:onRecord>
        </sx:subrecordMapping>
      </sx:onRecord>
    </eob>
  </sx:recordMapping>

</sx:resources>
]]>
        </programlisting>
      </figure>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i data/eobclaims.txt -r resources-eobclaims.xml eobclaims-to-xml
]]>
        </programlisting>
      </para>
    </section>
  </section>
  <section>
    <title>Many Flat Input Files</title>
    <section>
      <title>Multiple XML Readers</title>
      <titleabbrev>multiple-readers</titleabbrev>
      <indexterm>
        <primary>flat file</primary>
        <secondary>multiple readers</secondary>
      </indexterm>
      <para>This example shows a resources script that maps a primary input file
        to XML, with lookups from a secondary file.
      </para>
      <para>
The primary input file is the pipe delimited file,
<filename>primary-input.txt</filename>.
      </para>
        <programlisting>
          <![CDATA[
HDR|a|b 
DET|a|b 
DET|a|b 
MSG|1|a 
MSG|3|a 
END 
]]>
        </programlisting>
      <para>
The secondary input file is the pipe delimited file,                                                
<filename>messages.txt</filename>,
      </para>
        <programlisting>
          <![CDATA[
1|test message 1 
2|test message 2 
3|test message 3 
]]>
        </programlisting>
      <para>
You need to read the primary input file and replace the <sgmltag>id</sgmltag> 
        tag values under 
message with the message corresponding to the id. The expected output is
      </para>
        <programlisting>
          <![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<mytest>
  <field1>a</field1>
  <field2>b</field2>
  <detail>
    <field1>a</field1>
    <field2>b</field2>
  </detail>
  <detail>
    <field1>a</field1>
    <field2>b</field2>
  </detail>
  <message>
    <message>test message 1</message>
    <field2>a</field2>
  </message>
  <message>
    <message>test message 3</message>
    <field2>a</field2>
  </message>
</mytest>
]]>
        </programlisting>
      <para>
      </para>
      <para>The required resources script is
      </para>
      <programlisting>
        <![CDATA[
<sx:resources xmlns:sx="http://www.servingxml.com/core"
              xmlns:msv="http://www.servingxml.com/extensions/msv">

  <sx:service id="multiple-reader-test">
    <sx:serialize>
      <sx:xsltSerializer>
        <sx:outputProperty name="indent" value="yes"/>
      </sx:xsltSerializer>
      <sx:transform>
        <sx:content ref="multiple-reader-content"/>
      </sx:transform>
    </sx:serialize>
  </sx:service>

  <sx:recordContent id="multiple-reader-content">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:flatFile ref="primary-file"/>
      </sx:flatFileReader>
    </sx:recordStream>
    <sx:recordMapping ref="primary-file-to-xml"/>
  </sx:recordContent>

  <sx:flatFile id="primary-file">
    <sx:commentStarter value="#"/>
    <sx:flatFileBody>
      <sx:flatRecordTypeChoice>
        <sx:fieldDelimiter value="|"/>
        <sx:delimitedField name="tag"/>
        <sx:when test="tag='HDR'">
          <sx:flatRecordType name="header">
            <sx:delimitedField name="tag"/>
            <sx:delimitedField name="field1"/>
            <sx:delimitedField name="field2"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='DET'">
          <sx:flatRecordType name="detail">
            <sx:delimitedField name="tag"/>
            <sx:delimitedField name="field1"/>
            <sx:delimitedField name="field2"/>
          </sx:flatRecordType>
        </sx:when>
        <sx:when test="tag='MSG'">
          <sx:flatRecordType name="message">
            <sx:delimitedField name="tag"/>
            <sx:delimitedField name="field1"/>
            <sx:delimitedField name="field2"/>
          </sx:flatRecordType>
        </sx:when>
      </sx:flatRecordTypeChoice>
    </sx:flatFileBody>
  </sx:flatFile>

  <sx:recordMapping id="primary-file-to-xml">
    <mytest>
      <sx:onRecord recordType="header">
        <sx:fieldElementMap field="field1" element="field1"/>
        <sx:fieldElementMap field="field2" element="field2"/>
      </sx:onRecord>
      <sx:onRecord recordType="detail">
        <detail>
          <sx:fieldElementMap field="field1" element="field1"/>
          <sx:fieldElementMap field="field2" element="field2"/>
        </detail>
      </sx:onRecord>
      <sx:onRecord recordType="message">
        <message>
          <sx:parameter name="my-id" value="{field1}"/>
          <sx:fieldElementMap select="document('messageContent')/messages/message[id=$my-id]/description" element="message"/>
          <sx:fieldElementMap field="field2" element="field2"/>
        </message>
      </sx:onRecord>
    </mytest>
  </sx:recordMapping>

  <sx:recordContent id="messageContent" name="messages">
    <sx:recordStream>
      <sx:flatFileReader>
        <sx:urlSource url="messages.txt"/>
        <sx:flatFile ref="messagesFile"/>
      </sx:flatFileReader>
    </sx:recordStream>
  </sx:recordContent>

  <sx:flatFile id="messagesFile" name="messages">
    <sx:flatFileBody>
      <sx:fieldDelimiter value="|"/>
      <sx:flatRecordType name="message">
        <sx:delimitedField name="id"/>
        <sx:delimitedField name="description"/>
      </sx:flatRecordType>
    </sx:flatFileBody>
  </sx:flatFile>

</sx:resources>
]]>
      </programlisting>
      <para>
You can run this example on the command line by entering
        <programlisting>
          <![CDATA[
servingxml -i primary-input.txt -r resources.xml -o output.xml multiple-reader-test
]]>
        </programlisting>
      </para>
    </section>
  </section>
</section>


