FieldedText TypeScript Library
    Preparing search index...

    Read Sequence Example

    This example demonstrates reading CSV files with sequences, where different records have different field structures based on field values.

    Deserializes sequence metadata from an XML string, then reads a pet database where each record type has different fields:

    Reads a pet database where each record type (Cat, Dog, Goldfish) has different fields:

    • Cats (Type=1): Type, Name, RunningSpeed
    • Dogs (Type=2): Type, Name, WalkDistance, RunningSpeed, Training
      • If Training=true: also Trainer, SessionCost
    • Goldfish (Type=3): Type, Name, Color, ChineseClassification
    1. Sequences: Define groups of fields that appear together
    2. Sequence Redirects: Conditional field structures based on field values
    3. AutoNextTable: Automatically continue reading across table boundaries
    4. Table Boundaries: When sequence structure changes, a new "table" starts
    5. Field Access by Name: Use getFieldByName() to access fields in active sequences
    6. Meta Deserialization: Load metadata from XML text with FtXmlMetaSerialization.deserialize()
    1,Misty,45
    1,Oscar,35
    2,Buddy,0.5,35,false
    2,Charlie,2,48,true,John,32
    2,Max,0.5,30,false
    3,Bubbles,Orange,Wen
    3,Flash,Yellow,Crucian
    npx tsx examples/read-sequence/index.ts
    
    Reading pets with sequences:
    
    1: 1,Misty,45
    2: 1,Oscar,35
    3: 2,Buddy,0.5,35,false
    4: 2,Charlie,2,48,true,John,32
    5: 2,Max,0.5,30,false
    6: 3,Bubbles,Orange,Wen
    7: 3,Flash,Yellow,Crucian
    
    Total records: 7
    
    • autoNextTable = true: Required to read across table boundaries automatically
    • Field Names: Accessing fields by name works across all sequences
    • Conditional Logic: Application must check redirect field values to know which fields are present
    // Read Sequence Example
    // Demonstrates reading a CSV file with sequences (conditional field structures)
    // Uses the pet metadata from build-meta-with-sequences example

    import { FtReader, FtXmlMetaSerialization } from "@pbkware/fielded-text-web";

    // Sample CSV data with sequences
    const csvData = `1,Misty,45
    1,Oscar,35
    2,Buddy,0.5,35,False
    2,Charlie,2,48,True,John,32
    2,Max,0.5,30,False
    3,Bubbles,Orange,Wen
    3,Flash,Yellow,Crucian`;

    // Define Type values
    const CatType = BigInt(1);
    const DogType = BigInt(2);
    const GoldFishType = BigInt(3);

    // Define Field Names
    const TypeFieldName = "Type";
    const NameFieldName = "Name";
    const RunningSpeedFieldName = "RunningSpeed";
    const WalkDistanceFieldName = "WalkDistance";
    const TrainingFieldName = "Training";
    const TrainerFieldName = "Trainer";
    const SessionCostFieldName = "SessionCost";
    const ColorFieldName = "Color";
    const ChineseClassificationFieldName = "ChineseClassification";

    // Load metadata from XML string
    const metaXml = `<?xml version="1.0" encoding="utf-8"?>
    <FieldedText>
    <Field DataType="Integer" Name="Type" />
    <Field Id="1" Name="Name" />
    <Field DataType="Float" Id="2" Name="RunningSpeed" />
    <Field DataType="Float" Id="3" Name="WalkDistance" />
    <Field DataType="Boolean" Id="4" Name="Training" />
    <Field Id="5" Name="Trainer" />
    <Field DataType="Decimal" Id="6" Name="SessionCost" />
    <Field Id="7" Name="Color" />
    <Field Id="8" Name="ChineseClassification" />
    <Sequence Name="Root" Root="True">
    <Item FieldIndex="0">
    <Redirect SequenceName="Cat" InvokationDelay="AfterSequence" Value="1" />
    <Redirect SequenceName="Dog" InvokationDelay="AfterSequence" Value="2" />
    <Redirect SequenceName="GoldFish" InvokationDelay="AfterSequence" Value="3" />
    </Item>
    <Item FieldIndex="1" />
    </Sequence>
    <Sequence Name="Cat">
    <Item FieldIndex="2" />
    </Sequence>
    <Sequence Name="Dog">
    <Item FieldIndex="3" />
    <Item FieldIndex="2" />
    <Item FieldIndex="4">
    <Redirect SequenceName="Training" InvokationDelay="AfterField" Value="True" />
    </Item>
    </Sequence>
    <Sequence Name="GoldFish">
    <Item FieldIndex="7" />
    <Item FieldIndex="8" />
    </Sequence>
    <Sequence Name="Training">
    <Item FieldIndex="5" />
    <Item FieldIndex="6" />
    </Sequence>
    </FieldedText>`;

    const meta = FtXmlMetaSerialization.deserialize(metaXml);

    // Create reader
    const reader = new FtReader(meta, csvData);

    // Set AutoNextTable to true so read() continues across table boundaries
    // (Tables change when sequences redirect to a different structure)
    reader.autoNextTable = true;

    console.log("Reading pets with sequences:\n");

    // Read each record
    let recNumber = 0;
    while (reader.read()) {
    recNumber++;

    // Read root sequence fields (always present)
    const type = reader.getFieldByName(TypeFieldName)?.asBigInt;
    const name = reader.getFieldByName(NameFieldName)?.asString;

    const values: unknown[] = [type, name];

    // Type field determines which sequence is active and what fields are available
    if (type === CatType) {
    const runningSpeed = reader.getFieldByName(RunningSpeedFieldName)?.asFloat;
    values.push(runningSpeed);
    } else if (type === DogType) {
    const walkDistance = reader.getFieldByName(WalkDistanceFieldName)?.asFloat;
    const runningSpeed = reader.getFieldByName(RunningSpeedFieldName)?.asFloat;
    const training = reader.getFieldByName(TrainingFieldName)?.asBoolean;
    values.push(walkDistance, runningSpeed, training);

    if (training) {
    const trainer = reader.getFieldByName(TrainerFieldName)?.asString;
    const sessionCost =
    reader.getFieldByName(SessionCostFieldName)?.asDecimal;
    values.push(trainer, sessionCost);
    }
    } else if (type === GoldFishType) {
    const color = reader.getFieldByName(ColorFieldName)?.asString;
    const classification = reader.getFieldByName(
    ChineseClassificationFieldName,
    )?.asString;
    values.push(color, classification);
    }

    console.log(`${recNumber}: ${values.join(",")}`);
    }

    console.log(`\nTotal records: ${recNumber}`);