This is an automated email from the ASF dual-hosted git repository.
olabusayo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git
The following commit(s) were added to refs/heads/main by this push:
new 75801c140 Add warning for `dfdl:occursCountKind=parsed` without
`dfdl:separatorSuppressionPolicy=anyEmpty`
75801c140 is described below
commit 75801c1405432433e5db27f465bd87ac335c5b08
Author: olabusayoT <[email protected]>
AuthorDate: Wed Jan 21 15:04:21 2026 -0500
Add warning for `dfdl:occursCountKind=parsed` without
`dfdl:separatorSuppressionPolicy=anyEmpty`
- Introduced `TestImplicitvParsed` including TDML tests for
`occursCountKind=parsed` and `occursCountKind=implicit`.
- Added "SeparatorSuppressionPolicyError" warning to enforce
`separatorSuppressionPolicy="anyEmpty"` for `occursCountKind=parsed`.
- Implicit with SSP=trailingEmpty works as expected, with it looking for
the prefix / for absent arre1 in e2 in the added implicitvparsed.tdml as per
the spec (Table 47: RepDef(min) ~ Rep(max - min), which means RepDef(1)
followed by Rep(2), so it expects the separator for the last empty arre1
element), so the right thing to do if we don't want the empty trailing / is to
use anyEmpty
- Add SSP warning and specify error message in SequenceGroupDelimiters TDML
test
- Updated test cases to align with these changes.
DAFFODIL-2801
---
.../apache/daffodil/core/dsom/SequenceGroup.scala | 23 +++-
.../resources/org/apache/daffodil/xsd/dafext.xsd | 1 +
.../section14/occursCountKind/implicitvparsed.tdml | 134 +++++++++++++++++++++
.../sequence_groups/SequenceGroupDelimiters.tdml | 9 +-
.../org/apache/daffodil/usertests/SepTests.tdml | 4 +-
.../occursCountKind/TestImplicitvParsed.scala | 35 ++++++
6 files changed, 201 insertions(+), 5 deletions(-)
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala
index aa143c092..a6a9bc003 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala
@@ -102,6 +102,7 @@ abstract class SequenceGroupTermBase(xml: Node,
lexicalParent: SchemaComponent,
with SeparatorSuppressionPolicyMixin {
requiredEvaluationsIfActivated(checkIfValidUnorderedSequence)
+ requiredEvaluationsIfActivated(checkValidityOccursCountKind)
requiredEvaluationsIfActivated(checkIfNonEmptyAndDiscrimsOrAsserts)
requiredEvaluationsIfActivated(checkIfMultipleChildrenWithSameName)
@@ -160,6 +161,24 @@ abstract class SequenceGroupTermBase(xml: Node,
lexicalParent: SchemaComponent,
}
}.value
+ lazy val checkValidityOccursCountKind: Unit = {
+ if (hasSeparator && (separatorSuppressionPolicy ne
SeparatorSuppressionPolicy.AnyEmpty)) {
+ val optInvalidChild = groupMembers.find {
+ case e: ElementBase => e.occursCountKind == OccursCountKind.Parsed
+ case _ => false
+ }
+ if (optInvalidChild.isDefined) {
+ optInvalidChild.get.SDW(
+ WarnID.SeparatorSuppressionPolicyError,
+ "Member of a sequence with dfdl:occursCountKind='parsed' must have a
" +
+ "containing sequence with
dfdl:separatorSuppressionPolicy='anyEmpty', " +
+ "but was %s. This may be changed to an error in a future version
of Daffodil.",
+ separatorSuppressionPolicy
+ )
+ }
+ }
+ }
+
/**
* Provides validation for assert and discriminator placement
*/
@@ -181,12 +200,12 @@ abstract class SequenceGroupTermBase(xml: Node,
lexicalParent: SchemaComponent,
protected final lazy val checkIfValidUnorderedSequence: Unit = {
if (!isOrdered) {
checkMembersAreAllElementOrElementRef
- checkMembersHaveValidOccursCountKind
+ checkUnorderedSequenceMembersHaveValidOccursCountKind
checkUnorderedSequenceMembersHaveUniqueNamesInNamespaces
}
}
- private lazy val checkMembersHaveValidOccursCountKind: Unit = {
+ private lazy val checkUnorderedSequenceMembersHaveValidOccursCountKind: Unit
= {
val validChildren: Seq[ElementBase] =
groupMembers
.filter { m => m.isInstanceOf[LocalElementDecl] ||
m.isInstanceOf[ElementRef] }
diff --git
a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
index 719870bb2..8e0398c04 100644
--- a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
+++ b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
@@ -755,6 +755,7 @@
<xs:enumeration value="patternEncodingSlashW" />
<xs:enumeration value="queryStylePathExpression" />
<xs:enumeration value="regexPatternZeroLength" />
+ <xs:enumeration value="separatorSuppressionPolicyError" />
<xs:enumeration value="signedBinaryIntegerLength1Bit" />
<xs:enumeration value="textBidiError" />
<xs:enumeration value="textNumberPatternWarning" />
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/implicitvparsed.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/implicitvparsed.tdml
new file mode 100644
index 000000000..1a68f470b
--- /dev/null
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/implicitvparsed.tdml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<tdml:testSuite xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:ex="http://example.com" suiteName="rothrsreq" description="testing otg
gold schemas" defaultRoundTrip="true">
+ <tdml:defineSchema name="otg-schema" elementFormDefault="unqualified"
useDefaultNamespace="false">
+ <xs:include
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+ <dfdl:defineFormat name="DefaultPropertiesFormat">
+ <dfdl:format ref="ex:GeneralFormat"
+ emptyValueDelimiterPolicy="none"
+ fillByte="0"
+ lengthKind="delimited"
+ lengthUnits="characters"
+ nilKind="literalValue"
+ nilValue="%ES;"
+ nilValueDelimiterPolicy="none"
+ representation="text"
+ separatorPosition="infix"
+ separatorSuppressionPolicy="anyEmpty"
+ textNumberPadCharacter="0"
+ textNumberPattern="###0.###;-###0.###"
+ textPadKind="none"
+ textStandardZeroRep="" />
+ </dfdl:defineFormat>
+ <dfdl:format ref="ex:DefaultPropertiesFormat"/>
+
+ <xs:element name="e1">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="/" dfdl:separatorPosition="prefix"
dfdl:terminator="%NL;">
+ <xs:element name="se1" type="xs:int"/>
+ <xs:element name="se2" type="xs:int"/>
+ <xs:element name="arre1" maxOccurs="3" dfdl:occursCountKind="parsed">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="-">
+ <xs:choice>
+ <xs:element name="ie1" type="xs:int"/>
+ <xs:element name="ie2" type="xs:float"/>
+ </xs:choice>
+ <xs:element name="ie3" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="se5" type="xs:string"/>
+ <xs:element name="se6" type="xs:int"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="e2">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="/" dfdl:separatorPosition="prefix"
dfdl:terminator="%NL;">
+ <xs:element name="se1" type="xs:int"/>
+ <xs:element name="se2" type="xs:int"/>
+ <xs:element name="arre1" maxOccurs="3"
dfdl:occursCountKind="implicit">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="-">
+ <xs:choice>
+ <xs:element name="ie1" type="xs:int"/>
+ <xs:element name="ie2" type="xs:float"/>
+ </xs:choice>
+ <xs:element name="ie3" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="se5" type="xs:string"/>
+ <xs:element name="se6" type="xs:int"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </tdml:defineSchema>
+
+ <tdml:parserTestCase name="test_array_parsed" root="e1" model="otg-schema"
roundTrip="none">
+ <tdml:document><![CDATA[/1/2/3.5-one/4-two/a/6
+]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e1>
+ <se1>1</se1>
+ <se2>2</se2>
+ <arre1>
+ <ie2>3.5</ie2>
+ <ie3>one</ie3>
+ </arre1>
+ <arre1>
+ <ie1>4</ie1>
+ <ie3>two</ie3>
+ </arre1>
+ <se5>a</se5>
+ <se6>6</se6>
+ </ex:e1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="test_array_implicit" root="e2" model="otg-schema"
roundTrip="none">
+ <tdml:document><![CDATA[/1/2/3.5-one/4-two/a/6
+]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e2>
+ <se1>1</se1>
+ <se2>2</se2>
+ <arre1>
+ <ie2>3.5</ie2>
+ <ie3>one</ie3>
+ </arre1>
+ <arre1>
+ <ie1>4</ie1>
+ <ie3>two</ie3>
+ </arre1>
+ <se5>a</se5>
+ <se6>6</se6>
+ </ex:e2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+</tdml:testSuite>
\ No newline at end of file
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroupDelimiters.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroupDelimiters.tdml
index d3f10849f..4f9af2023 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroupDelimiters.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroupDelimiters.tdml
@@ -296,8 +296,15 @@
<tdml:document><![CDATA[1,2,3,4,5,6
]]></tdml:document>
+
+ <tdml:warnings>
+ <tdml:warning>occursCountKind='parsed'</tdml:warning>
+ <tdml:warning>must have</tdml:warning>
+ <tdml:warning>separatorSuppressionPolicy='anyEmpty'</tdml:warning>
+ <tdml:warning>but was never</tdml:warning>
+ </tdml:warnings>
<tdml:errors>
- <tdml:error></tdml:error>
+ <tdml:error>left over data</tdml:error>
</tdml:errors>
</tdml:parserTestCase>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
index 61d08de6b..5878e386f 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
@@ -456,11 +456,11 @@
<xs:element name="root" dfdl:initiator="RECORD">
<xs:complexType>
- <xs:sequence dfdl:separator="/" dfdl:separatorPosition="prefix"
dfdl:terminator="%NL;">
+ <xs:sequence dfdl:separator="/" dfdl:separatorPosition="prefix"
dfdl:terminator="%NL;" dfdl:separatorSuppressionPolicy="anyEmpty">
<xs:element name="field1" type="xs:string" />
<xs:element name="field2" type="xs:string" minOccurs="0" />
<xs:element name="field3" type="xs:string" minOccurs="0" />
- <xs:element name="groupOfFields" minOccurs="1" maxOccurs="3"
dfdl:occursCountKind="parsed">
+ <xs:element name="groupOfFields" minOccurs="1" maxOccurs="3">
<xs:complexType>
<xs:sequence>
<xs:sequence dfdl:separator="/" dfdl:separatorPosition="infix"
dfdl:separatorSuppressionPolicy="never">
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section14/occursCountKind/TestImplicitvParsed.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section14/occursCountKind/TestImplicitvParsed.scala
new file mode 100644
index 000000000..26a5dc5ba
--- /dev/null
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section14/occursCountKind/TestImplicitvParsed.scala
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.section14.occursCountKind
+
+import org.apache.daffodil.junit.tdml.TdmlSuite
+import org.apache.daffodil.junit.tdml.TdmlTests
+
+import org.junit.Test
+
+object TestImplicitvParsed extends TdmlSuite {
+ val tdmlResource =
"org/apache/daffodil/section14/occursCountKind/implicitvparsed.tdml"
+}
+
+class TestImplicitvParsed extends TdmlTests {
+ val tdmlSuite = TestImplicitvParsed
+
+ @Test def test_array_parsed = test
+ @Test def test_array_implicit = test
+
+}