Example #1
0
 public void InsertFieldTest()
 {
     Record target = new Record();
     string tag = "245";
     target.Fields.Add(new ControlField("001", "I am data! (But not Data from Star Trek TNG)"));
     target.Fields.Add(new DataField(tag));
     target.Fields.Add(new DataField("521", new List<Subfield>(), ' ', '1'));
     Field newField = new DataField("300", new List<Subfield>(), '0', '1');
     target.InsertField(newField);
     Assert.AreSame(newField, target.Fields[2]);
 }
Example #2
0
        public void CloneTest()
        {
            string tag = "100";
            List<Subfield> subfields = new List<Subfield>();
            Subfield subfield = new Subfield('a', "It's a book!");
            subfields.Add(subfield);
            subfield = new Subfield('b', "Anne Author");
            subfields.Add(subfield);
            Field target = new DataField(tag, subfields);
            Field actual;
            actual = target.Clone();
            Assert.AreNotEqual(target, actual);

            target.Tag = "200";

            string expectedString = tag;
            string actualString;
            actualString = actual.Tag;
            Assert.AreEqual(expectedString, actualString);

            ((DataField)target).Indicator1 = '1';
            ((DataField)target).Indicator2 = '2';

            expectedString = "  ";
            actualString = ((DataField)actual).Indicator1.ToString() + ((DataField)actual).Indicator2.ToString();
            Assert.AreEqual(expectedString, actualString);

            ((DataField)target)['a'].Code = 'c';
            ((DataField)target)['c'].Data = "It's a NEW book!";

            expectedString = "aIt's a book!";
            actualString = ((DataField)actual)['a'].Code.ToString() + ((DataField)actual)['a'].Data;
            Assert.AreEqual(expectedString, actualString);

            //This next line will fail as there's no subfield c!
            ((DataField)actual)['c'].Code = 'a';
        }
Example #3
0
        public void FieldsTest()
        {
            Record target = new Record();
            ControlField controlField = new ControlField("001", "I am data! (But not Data from Star Trek TNG)");
            DataField dataField = new DataField("245");
            DataField dataField2 = new DataField("521", new List<Subfield>(), ' ', '1');
            target.Fields.Add(controlField);
            target.Fields.Add(dataField);
            target.Fields.Add(dataField2);

            {
                int expected = 3;
                int actual;
                actual = target.Fields.Count;
                Assert.AreEqual(expected, actual);
            }

            {
                Field expected = controlField;
                Field actual;
                actual = target.Fields[0];
                Assert.AreSame(expected, actual);
                expected = dataField;
                actual = target.Fields[1];
                Assert.AreSame(expected, actual);
                expected = dataField2;
                actual = target.Fields[2];
                Assert.AreSame(expected, actual);
            }

            {
                List<Field> expected = new List<Field>();
                expected.Add(controlField);
                expected.Add(dataField);
                expected.Add(dataField2);
                target.Fields = expected;
                List<Field> actual;
                actual = target.Fields;
                Assert.AreSame(expected, actual);
            }
        }
Example #4
0
 public void ToRawTest()
 {
     string tag = "100";
     List<Subfield> subfields = new List<Subfield>();
     Subfield subfield = new Subfield('a', "It's a book!");
     subfields.Add(subfield);
     subfield = new Subfield('b', "Anne Author");
     subfields.Add(subfield);
     DataField target = new DataField(tag, subfields);
     string expected = "  " + FileMARC.SUBFIELD_INDICATOR.ToString() + "aIt's a book!" + FileMARC.SUBFIELD_INDICATOR.ToString() + "bAnne Author" + FileMARC.END_OF_FIELD.ToString();
     string actual;
     actual = target.ToRaw();
     Assert.AreEqual(expected, actual);
 }
Example #5
0
 public void ToStringTest()
 {
     string tag = "100";
     List<Subfield> subfields = new List<Subfield>();
     Subfield subfield = new Subfield('a', "It's a book!");
     subfields.Add(subfield);
     subfield = new Subfield('b', "Anne Author");
     subfields.Add(subfield);
     DataField target = new DataField(tag, subfields);
     string expected = "100    [a]: It's a book!" + Environment.NewLine + "       [b]: Anne Author";
     string actual;
     actual = target.ToString();
     Assert.AreEqual(expected, actual);
 }
Example #6
0
        /// <summary>
        /// Decodes the raw MARC record into a <see cref="MARC.Record"/> at the specified index.///
        /// </summary>
        /// <param name="index">The index of the record to retrieve.</param>
        /// <returns></returns>
        private Record Decode(int index)
        {
            string raw          = _rawSource[index];
            Record marc         = new Record();
            Match  match        = Regex.Match(raw, "^(\\d{5})");
            int    recordLength = 0;

            // Store record length
            if (match.Captures.Count == 0)
            {
                marc.AddWarnings("MARC record length is not numeric.");
            }
            else
            {
                recordLength = Convert.ToInt32(match.Captures[0].Value);
            }

            if (recordLength != raw.Length)
            {
                marc.AddWarnings("MARC record length does not match actual length.");
                recordLength = raw.Length;
            }

            if (!raw.EndsWith(END_OF_RECORD.ToString()))
            {
                throw new InvalidDataException("MARC record ends with an invalid terminator");
            }

            //Store leader
            marc.Leader = raw.Substring(0, LEADER_LEN);

            //Bytes 12-16 of leader give offset to the body of the record
            int dataStart = Convert.ToInt32(raw.Substring(12, 5));

            //Immediately after the leader comes the directory (no separator)
            string directory = raw.Substring(LEADER_LEN, dataStart - LEADER_LEN - 1);

            //Character after the directory should be END_OF_FIELD
            if (raw.Substring(dataStart - 1, 1) != END_OF_FIELD.ToString())
            {
                marc.AddWarnings("No directory found.");
            }

            //All directory entries must be DIRECTORY_ENTRY_LEN long, so length % DIRECTORY_ENTRY_LEN should be 0
            if (directory.Length % DIRECTORY_ENTRY_LEN != 0)
            {
                marc.AddWarnings("Invalid directory length.");
            }

            //Go through all the fields
            int fieldCount = directory.Length / DIRECTORY_ENTRY_LEN;

            for (int i = 0; i < fieldCount; i++)
            {
                string tag         = directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(0, 3);
                int    fieldLength = 0;
                int    fieldOffset = 0;
                try
                {
                    fieldLength = Convert.ToInt32(directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(3, 4));
                }
                catch (FormatException)
                {
                    marc.AddWarnings("Invalid Directory Tag Length for tag " + tag + ".");
                }

                try
                {
                    fieldOffset = Convert.ToInt32(directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(7, 5));
                }
                catch (FormatException)
                {
                    marc.AddWarnings("Invalid Directory Offset for tag " + tag + ".");
                }

                //Check Directory validity

                //If a tag isn't valid, default it to ZZZ. This should at least make the record valid enough to be readable and not throw exceptions
                if (!Field.ValidateTag(tag))
                {
                    marc.AddWarnings("Invalid tag " + tag + " in directory.");
                    tag = "ZZZ";
                }

                if (fieldOffset + fieldLength > recordLength)
                {
                    marc.AddWarnings("Directory entry for tag " + tag + " runs past the end of the record.");
                }

                int fieldStart = dataStart + fieldOffset;
                if (fieldStart > recordLength)
                {
                    marc.AddWarnings("Directory entry for tag " + tag + " starts past the end of the record. Skipping tag and all proceeding tags.");
                    break;
                }
                else if (fieldStart + fieldLength > recordLength)
                {
                    marc.AddWarnings("Directory entry for tag " + tag + " runs past the end of the record.");
                    fieldLength = recordLength - fieldStart;
                }
                string tagData = raw.Substring(fieldStart, fieldLength);

                if (tagData.Substring(tagData.Length - 1, 1) == END_OF_FIELD.ToString())
                {
                    //Get rid of the end of tag character
                    tagData = tagData.Remove(tagData.Length - 1);
                    fieldLength--;
                }
                else
                {
                    marc.AddWarnings("Field for tag " + tag + " does not end with an end of field character.");
                }

                match = Regex.Match(tag, "^\\d+$");
                if (match.Captures.Count > 0 && Convert.ToInt32(tag) < 10)
                {
                    marc.Fields.Add(new ControlField(tag, tagData));
                }
                else
                {
                    List <string> rawSubfields = new List <string>(tagData.Split(SUBFIELD_INDICATOR));
                    string        indicators   = rawSubfields[0];
                    rawSubfields.RemoveAt(0);

                    char ind1;
                    char ind2;

                    if (indicators.Length != 2)
                    {
                        marc.AddWarnings("Invalid indicator length. Forced indicators to blanks for tag " + tag + ".");
                        ind1 = ind2 = ' ';
                    }
                    else
                    {
                        ind1 = char.ToLower(indicators[0]);

                        if (!DataField.ValidateIndicator(ind1))
                        {
                            ind1 = ' ';
                            marc.AddWarnings("Invalid first indicator. Forced first indicator to blank for tag " + tag + ".");
                        }

                        ind2 = char.ToLower(indicators[1]);

                        if (!DataField.ValidateIndicator(ind2))
                        {
                            ind2 = ' ';
                            marc.AddWarnings("Invalid second indicator. Forced second indicator to blank for tag " + tag + ".");
                        }
                    }

                    //Split the subfield data into subfield name and data pairs
                    List <Subfield> subfieldData = new List <Subfield>();
                    foreach (string subfield in rawSubfields)
                    {
                        if (subfield.Length > 0)
                        {
                            subfieldData.Add(new Subfield(subfield[0], subfield.Substring(1)));
                        }
                        else
                        {
                            marc.AddWarnings("No subfield data found in tag " + tag + ".");
                        }
                    }

                    if (subfieldData.Count == 0)
                    {
                        marc.AddWarnings("No subfield data found in tag " + tag + ".");
                    }

                    marc.Fields.Add(new DataField(tag, subfieldData, ind1, ind2));
                }
            }
            return(marc);
        }
Example #7
0
        public void SubfieldsTest()
        {
            string tag = "100";
            List<Subfield> subfields = new List<Subfield>();
            Subfield subfield = new Subfield('a', "It's a book!");
            subfields.Add(subfield);
            subfield = new Subfield('b', "Anne Author");
            subfields.Add(subfield);
            DataField target = new DataField(tag, subfields);
            List<Subfield> expected = new List<Subfield>();
            subfield = new Subfield('a', "It's another book!");
            expected.Add(subfield);
            subfield = new Subfield('b', "Anne Otter Author");
            expected.Add(subfield);
            List<Subfield> actual;
            target.Subfields = expected;
            actual = target.Subfields;

            Assert.AreEqual(expected.Count, actual.Count);
            for (int i = 0; i < expected.Count; i++)
            {
                Assert.AreEqual(expected[i].Code, actual[i].Code);
                Assert.AreEqual(expected[i].Data, actual[i].Data);
            }
        }
Example #8
0
 public void Indicator2Test()
 {
     string tag = "100";
     DataField target = new DataField(tag);
     char expected = '1';
     char actual;
     target.Indicator2 = expected;
     actual = target.Indicator2;
     Assert.AreEqual(expected, actual);
     expected = '%';
     target.Indicator2 = expected; //Will throw exception
 }
Example #9
0
 public void IsEmptyTest()
 {
     string tag = "100";
     DataField target = new DataField(tag);
     bool expected = true;
     bool actual;
     actual = target.IsEmpty();
     Assert.AreEqual(expected, actual);
     List<Subfield> subfields = new List<Subfield>();
     Subfield subfield = new Subfield('a', "It's a book!");
     subfields.Add(subfield);
     subfield = new Subfield('b', "Anne Author");
     subfields.Add(subfield);
     subfield = new Subfield('b', "Anne Otter Author");
     subfields.Add(subfield);
     target = new DataField(tag, subfields);
     expected = false;
     actual = target.IsEmpty();
     Assert.AreEqual(expected, actual);
 }
Example #10
0
        public void DataFieldConstructorTest3()
        {
            string tag = "100";
            List<Subfield> subfields = new List<Subfield>();
            Subfield subfield = new Subfield('a', "It's a book!");
            subfields.Add(subfield);
            subfield = new Subfield('b', "Anne Author");
            subfields.Add(subfield);
            char ind1 = '1';
            DataField target = new DataField(tag, subfields, ind1);

            {
                char expected = '1';
                char actual = target.Indicator1;
                Assert.AreEqual(expected, actual);
                expected = ' ';
                actual = target.Indicator2;
                Assert.AreEqual(expected, actual);
                expected = 'a';
                actual = target['a'].Code;
                Assert.AreEqual(expected, actual);
                expected = 'b';
                actual = target['b'].Code;
                Assert.AreEqual(expected, actual);
            }

            {
                string expected = "100";
                string actual = target.Tag;
                Assert.AreEqual(expected, actual);
                expected = "It's a book!";
                actual = target['a'].Data;
                Assert.AreEqual(expected, actual);
                expected = "Anne Author";
                actual = target['b'].Data;
                Assert.AreEqual(expected, actual);
            }

            {
                int expected = 2;
                int actual = target.Subfields.Count;
                Assert.AreEqual(expected, actual);
            }
        }
Example #11
0
 public void FormatFieldTest1()
 {
     string tag = "600";
     List<Subfield> subfields = new List<Subfield>();
     Subfield subfield = new Subfield('a', "It's a book!");
     subfields.Add(subfield);
     subfield = new Subfield('b', "Anne Author");
     subfields.Add(subfield);
     subfield = new Subfield('c', "Some text");
     subfields.Add(subfield);
     subfield = new Subfield('d', "Some more text");
     subfields.Add(subfield);
     subfield = new Subfield('v', "Some fancy text");
     subfields.Add(subfield);
     subfield = new Subfield('z', "Some more fancy text");
     subfields.Add(subfield);
     DataField target = new DataField(tag, subfields);
     string expected = "It's a book! Anne Author Some text Some more text -- Some fancy text -- Some more fancy text";
     string actual;
     actual = target.FormatField();
     Assert.AreEqual(expected, actual);
 }
Example #12
0
        public void DataFieldConstructorTest1()
        {
            string tag = "100";
            DataField target = new DataField(tag);

            {
                string expected = "100";
                string actual = target.Tag;
                Assert.AreEqual(expected, actual);
            }

            {
                char expected = ' ';
                char actual = target.Indicator1;
                Assert.AreEqual(expected, actual);
                actual = target.Indicator2;
                Assert.AreEqual(expected, actual);
            }

            {
                int expected = 0;
                int actual = target.Subfields.Count;
                Assert.AreEqual(expected, actual);
            }
        }
Example #13
0
 /// <summary>
 /// Makes a deep clone of this instance.
 /// </summary>
 /// <returns></returns>
 public override Field Clone()
 {
     Field clone = new DataField(Tag, new List<Subfield>(), _ind1, _ind2);
     foreach (Subfield needsCloned in Subfields)
         ((DataField)clone).Subfields.Add(needsCloned.Clone());
     return clone;
 }
Example #14
0
 internal virtual Field CreateDataField()
 {
     List<Subfield> subfields = new List<Subfield>();
     subfields.Add(new Subfield('a', "It's a book!"));
     subfields.Add(new Subfield('b', "Anne Author"));
     Field target = new DataField("100", subfields, '1', ' ');
     return target;
 }
Example #15
0
 public void ItemTest()
 {
     Record target = new Record();
     string tag = "245";
     ControlField controlField = new ControlField("001", "I am data! (But not Data from Star Trek TNG)");
     DataField dataField = new DataField(tag);
     DataField dataField2 = new DataField(tag, new List<Subfield>(), ' ', '1');
     target.Fields.Add(controlField);
     target.Fields.Add(dataField);
     target.Fields.Add(dataField2);
     Field expected = dataField;
     Field actual;
     actual = target[tag];
 }
Example #16
0
 public void ItemTest()
 {
     string tag = "100";
     List<Subfield> subfields = new List<Subfield>();
     Subfield subfield = new Subfield('a', "It's a book!");
     subfields.Add(subfield);
     subfield = new Subfield('b', "Anne Author");
     subfields.Add(subfield);
     DataField target = new DataField(tag, subfields);
     char code = 'a';
     Subfield expected = new Subfield('a', "It's a book!");
     Subfield actual;
     actual = target[code];
     Assert.AreEqual(expected.Code, actual.Code);
     Assert.AreEqual(expected.Data, actual.Data);
 }
Example #17
0
        /// <summary>
        /// Decodes the raw MARC record into a <see cref="MARC.Record"/> at the specified index.///
        /// </summary>
        /// <param name="index">The index of the record to retrieve.</param>
        /// <returns></returns>
        private Record Decode(int index)
        {
            XElement record = _rawSource[index];
            Record marcXml = new Record();

            //First we get the leader
            marcXml.Leader = record.Elements().First(e => e.Name.LocalName == "leader").Value;

            //Now we get the control fields
            foreach (XElement controlField in record.Elements().Where(e => e.Name.LocalName == "controlfield"))
            {
                ControlField newField = new ControlField(controlField.Attribute("tag").Value, controlField.Value);
                marcXml.Fields.Add(newField);
            }

            //Now we get the data fields
            foreach (XElement dataField in record.Elements().Where(e => e.Name.LocalName == "datafield"))
            {
                DataField newField = new DataField(dataField.Attribute("tag").Value, new List<Subfield>(), dataField.Attribute("ind1").Value[0], dataField.Attribute("ind2").Value[0]);

                foreach (XElement subfield in dataField.Elements().Where(e => e.Name.LocalName == "subfield"))
                {
                    Subfield newSubfield = new Subfield(subfield.Attribute("code").Value[0], subfield.Value);
                    newField.Subfields.Add(newSubfield);
                }

                marcXml.Fields.Add(newField);
            }

            return marcXml;
        }
Example #18
0
        //Private utility functions
        #region Private utility functions

        /// <summary>
        /// Decodes the raw MARC record into a <see cref="MARC.Record"/> at the specified index.///
        /// </summary>
        /// <param name="index">The index of the record to retrieve.</param>
        /// <returns></returns>
        private Record decode(int index)
        {
            string raw                 = rawSource[index];
            Record marc                = new Record();
            Match  match               = Regex.Match(raw, "^(\\d{5})");
            int    recordLength        = 0;
            int    totalExtraBytesRead = 0;

            // Store record length
            if (match.Captures.Count == 0)
            {
                marc.AddWarnings("MARC record length is not numeric or incorrect number of characters.");
                string[] split = Regex.Split(raw, "[^0-9]");

                if (Int32.TryParse(split[0], out recordLength))
                {
                    string padding = "";
                    padding = padding.PadLeft(5 - split[0].Length, '0');
                    raw     = padding + raw;
                }
            }
            else
            {
                recordLength = Convert.ToInt32(match.Captures[0].Value);
            }

            if (recordLength != raw.Length)
            {
                //Check if there are multi-byte characters in the string
                System.Globalization.StringInfo stringInfo = new System.Globalization.StringInfo(raw);

                int extraBytes  = raw.Length - stringInfo.LengthInTextElements;
                int extraBytes2 = Encoding.UTF8.GetByteCount(raw) - raw.Length;

                if (recordLength == extraBytes + raw.Length)
                {
                    recordLength -= extraBytes;
                }
                else if (recordLength == extraBytes2 + raw.Length)
                {
                    recordLength -= extraBytes2;
                }
                else
                {
                    marc.AddWarnings("MARC record length does not match actual length.");
                    recordLength = raw.Length;
                }
            }

            if (!raw.EndsWith(END_OF_RECORD.ToString()))
            {
                throw new InvalidDataException("MARC record ends with an invalid terminator");
            }

            //Store leader
            marc.Leader = raw.Substring(0, LEADER_LEN);

            //Bytes 12-16 of leader give offset to the body of the record
            int dataStart = Convert.ToInt32(raw.Substring(12, 5));

            //Verify data start matches the first end of field marker
            if (raw.IndexOf(END_OF_FIELD) + 1 != dataStart)
            {
                dataStart = raw.IndexOf(END_OF_FIELD) + 1;
                marc.AddWarnings("Leader specifies incorrect base address of data.");
            }

            //Immediately after the leader comes the directory (no separator)

            string directory = raw.Substring(LEADER_LEN, dataStart - LEADER_LEN - 1);

            //Character after the directory should be END_OF_FIELD
            if (raw.Substring(dataStart - 1, 1) != END_OF_FIELD.ToString())
            {
                marc.AddWarnings("No directory found.");
            }

            //All directory entries must be DIRECTORY_ENTRY_LEN long, so length % DIRECTORY_ENTRY_LEN should be 0
            if (directory.Length % DIRECTORY_ENTRY_LEN != 0)
            {
                marc.AddWarnings("Invalid directory length.");
            }

            //Go through all the fields
            int fieldCount = directory.Length / DIRECTORY_ENTRY_LEN;

            for (int i = 0; i < fieldCount; i++)
            {
                string tag         = directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(0, 3);
                int    fieldLength = 0;
                int    fieldOffset = 0;
                try
                {
                    fieldLength = Convert.ToInt32(directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(3, 4));
                }
                catch (FormatException)
                {
                    marc.AddWarnings("Invalid Directory Tag Length for tag " + tag + ".");
                }

                try
                {
                    fieldOffset = Convert.ToInt32(directory.Substring(i * DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN).Substring(7, 5)) + totalExtraBytesRead;
                }
                catch (FormatException)
                {
                    marc.AddWarnings("Invalid Directory Offset for tag " + tag + ".");
                }

                //Check Directory validity

                //If a tag isn't valid, default it to ZZZ. This should at least make the record valid enough to be readable and not throw exceptions
                if (!Field.ValidateTag(tag))
                {
                    marc.AddWarnings("Invalid tag " + tag + " in directory.");
                    tag = "ZZZ";
                }

                if (fieldOffset + fieldLength > recordLength)
                {
                    marc.AddWarnings("Directory entry for tag " + tag + " runs past the end of the record.");
                }

                int fieldStart = dataStart + fieldOffset - (totalExtraBytesRead * 2);
                if (fieldStart > recordLength)
                {
                    marc.AddWarnings("Directory entry for tag " + tag + " starts past the end of the record. Skipping tag and all proceeding tags.");
                    break;
                }
                else if (fieldStart + fieldLength > recordLength)
                {
                    marc.AddWarnings("Directory entry for tag " + tag + " runs past the end of the record.");
                    fieldLength = recordLength - fieldStart;
                }

                string tagData = raw.Substring(fieldStart, fieldLength);

                //Check if there are multi-byte characters in the string
                System.Globalization.StringInfo stringInfo = new System.Globalization.StringInfo(tagData);
                int extraBytes      = fieldLength - stringInfo.LengthInTextElements;
                int extraBytes2     = Encoding.UTF8.GetByteCount(tagData) - fieldLength;
                int endOfFieldIndex = tagData.IndexOf(END_OF_FIELD);

                if (tagData.Length - 1 != endOfFieldIndex)
                {
                    int differenceLength = tagData.Length - 1 - endOfFieldIndex;

                    if (differenceLength != extraBytes && differenceLength != extraBytes2)
                    {
                        fieldLength         -= differenceLength;
                        totalExtraBytesRead += differenceLength;
                        tagData              = raw.Substring(fieldStart, endOfFieldIndex + 1);
                    }
                    else
                    {
                        if (extraBytes > 0)
                        {
                            fieldLength         -= extraBytes;
                            totalExtraBytesRead += extraBytes;
                            tagData              = raw.Substring(fieldStart, fieldLength);
                        }
                        else if (extraBytes2 > 0)
                        {
                            fieldLength         -= extraBytes2;
                            totalExtraBytesRead += extraBytes2;
                            tagData              = raw.Substring(fieldStart, fieldLength);
                        }
                    }
                }

                if (fieldLength > 0)
                {
                    string endCharacter = tagData.Substring(tagData.Length - 1, 1);
                    if (endCharacter == END_OF_FIELD.ToString())
                    {
                        //Get rid of the end of tag character
                        tagData = tagData.Remove(tagData.Length - 1);
                        fieldLength--;
                    }
                    else
                    {
                        marc.AddWarnings("Field for tag " + tag + " does not end with an end of field character.");
                    }
                }
                else
                {
                    marc.AddWarnings("Field for tag " + tag + " has a length of 0.");
                }

                match = Regex.Match(tag, "^\\d+$");
                if (match.Captures.Count > 0 && Convert.ToInt32(tag) < 10)
                {
                    marc.Fields.Add(new ControlField(tag, tagData));
                }
                else
                {
                    List <string> rawSubfields = new List <string>(tagData.Split(SUBFIELD_INDICATOR));
                    string        indicators   = rawSubfields[0];
                    rawSubfields.RemoveAt(0);

                    char ind1;
                    char ind2;

                    if (indicators.Length != 2)
                    {
                        marc.AddWarnings("Invalid indicator length. Forced indicators to blanks for tag " + tag + ".");
                        ind1 = ind2 = ' ';
                    }
                    else
                    {
                        ind1 = char.ToLower(indicators[0]);

                        if (!DataField.ValidateIndicator(ind1))
                        {
                            ind1 = ' ';
                            marc.AddWarnings("Invalid first indicator. Forced first indicator to blank for tag " + tag + ".");
                        }

                        ind2 = char.ToLower(indicators[1]);

                        if (!DataField.ValidateIndicator(ind2))
                        {
                            ind2 = ' ';
                            marc.AddWarnings("Invalid second indicator. Forced second indicator to blank for tag " + tag + ".");
                        }
                    }

                    //Split the subfield data into subfield name and data pairs
                    List <Subfield> subfieldData = new List <Subfield>();
                    foreach (string subfield in rawSubfields)
                    {
                        if (subfield.Length > 0)
                        {
                            subfieldData.Add(new Subfield(subfield[0], subfield.Substring(1)));
                        }
                        else
                        {
                            marc.AddWarnings("No subfield data found in tag " + tag + ".");
                        }
                    }

                    if (subfieldData.Count == 0)
                    {
                        marc.AddWarnings("No subfield data found in tag " + tag + ".");
                    }

                    marc.Fields.Add(new DataField(tag, subfieldData, ind1, ind2));
                }
            }
            return(marc);
        }