diff --git a/Directory.Packages.props b/Directory.Packages.props
index fb1dcee..f0ba2a3 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -13,7 +13,7 @@
-
+
diff --git a/src/EncDotNet.Iso8211/Iso8211DataDescriptiveRecordReader.cs b/src/EncDotNet.Iso8211/Iso8211DataDescriptiveRecordReader.cs
index 0481042..f020aca 100644
--- a/src/EncDotNet.Iso8211/Iso8211DataDescriptiveRecordReader.cs
+++ b/src/EncDotNet.Iso8211/Iso8211DataDescriptiveRecordReader.cs
@@ -366,7 +366,8 @@ private static void ParseSubfieldLabels(
int starIndex = rawName.IndexOf('*');
if (starIndex > 0)
{
- string leaderName = rawName.Substring(0, starIndex);
+ // S-100 Part 10a writes "\\" just before the '*'; it is not part of the label.
+ string leaderName = TrimLabel(rawName.Substring(0, starIndex));
if (!string.IsNullOrEmpty(leaderName))
{
names.Add(leaderName);
@@ -378,6 +379,7 @@ private static void ParseSubfieldLabels(
}
}
+ rawName = TrimLabel(rawName);
if (!string.IsNullOrEmpty(rawName))
{
names.Add(rawName);
@@ -388,6 +390,11 @@ private static void ParseSubfieldLabels(
subfieldNames = names.ToImmutable();
}
+ ///
+ /// Removes the trailing backslashes S-100 Part 10a places before a repeating-group *.
+ ///
+ private static string TrimLabel(string label) => label.TrimEnd('\\');
+
///
/// Parses the descriptor portion of a DDR field into a field name and subfield names.
///
@@ -439,6 +446,7 @@ private static void ParseDescriptors(
rawName = rawName.Substring(1);
}
+ rawName = TrimLabel(rawName);
if (!string.IsNullOrEmpty(rawName))
{
names.Add(rawName);
diff --git a/tests/EncDotNet.UnitTests/Iso8211DataDescriptiveRecordReaderTests.cs b/tests/EncDotNet.UnitTests/Iso8211DataDescriptiveRecordReaderTests.cs
index 20d26b0..d34734b 100644
--- a/tests/EncDotNet.UnitTests/Iso8211DataDescriptiveRecordReaderTests.cs
+++ b/tests/EncDotNet.UnitTests/Iso8211DataDescriptiveRecordReaderTests.cs
@@ -1528,6 +1528,55 @@ public void Parse_TwoUtFormat_ConcatenatedArrayWithLeaderAndRepeating_ParsesCorr
Assert.True(c3il.SubfieldDefinitions[3].IsRepeating);
}
+ [Fact]
+ public void Parse_TwoUtFormat_S100BackslashesBeforeStar_AreTrimmedFromLeaderName()
+ {
+ // Arrange — S-100 Part 10a writes "\\" before the '*' that starts the repeating group
+ // (S-101 2.0 DSID descriptor).
+ var record = CreateDdrRecordTwoUt(
+ tag: "DSID",
+ dataStructureCode: '1',
+ dataTypeCode: '6',
+ fieldName: "Dataset Identification",
+ subfieldLabels: @"RCNM!RCID!ENSP!ENED!PRSP!PRED!PROF!DSNM!DSTL!DSRD!DSLG!DSAB!DSED\\*DSTC",
+ formatControls: "(b11,b14,11A,b11)");
+
+ // Act
+ var ddr = Iso8211DataDescriptiveRecordReader.Read(record);
+ var dsid = ddr.FieldDefinitions[0];
+
+ // Assert
+ Assert.Equal(14, dsid.SubfieldDefinitions.Count);
+ Assert.Equal("DSED", dsid.SubfieldDefinitions[12].Name);
+ Assert.Equal("DSTC", dsid.SubfieldDefinitions[13].Name);
+ Assert.Equal(13, dsid.RepeatingSubfieldStartIndex);
+ Assert.False(dsid.SubfieldDefinitions[12].IsRepeating);
+ Assert.True(dsid.SubfieldDefinitions[13].IsRepeating);
+ }
+
+ [Fact]
+ public void Parse_TwoUtFormat_S100BackslashesBeforeStar_SingleLeaderSubfield()
+ {
+ // Arrange — S-101 2.0 C3IL descriptor
+ var record = CreateDdrRecordTwoUt(
+ tag: "C3IL",
+ dataStructureCode: '3',
+ dataTypeCode: '5',
+ fieldName: "3-D Integer Coordinate List",
+ subfieldLabels: @"VCID\\*YCOO!XCOO!ZCOO",
+ formatControls: "(b11,3b24)");
+
+ // Act
+ var ddr = Iso8211DataDescriptiveRecordReader.Read(record);
+ var c3il = ddr.FieldDefinitions[0];
+
+ // Assert
+ Assert.Equal(4, c3il.SubfieldDefinitions.Count);
+ Assert.Equal("VCID", c3il.SubfieldDefinitions[0].Name);
+ Assert.Equal("YCOO", c3il.SubfieldDefinitions[1].Name);
+ Assert.Equal(1, c3il.RepeatingSubfieldStartIndex);
+ }
+
[Fact]
public void Parse_TwoUtFormat_VectorStyleStarAtStart_StillWorks()
{