diff --git a/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/TestCLIParsing.scala b/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/TestCLIParsing.scala
index 51eb670610..622c92d3ea 100644
--- a/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/TestCLIParsing.scala
+++ b/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/TestCLIParsing.scala
@@ -358,7 +358,7 @@ class TestCLIParsing {
runCLI(args"parse -s $schema -r unknown") { cli =>
cli.sendLine("12", inputDone = true)
- cli.expectErr("No root element found for unknown in any available namespace")
+ cli.expectErr("No root element found for {}unknown")
}(ExitCode.UnableToCreateProcessor)
}
diff --git a/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/schematron/TestSvrlOutput.scala b/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/schematron/TestSvrlOutput.scala
index b728d47938..1800b1808d 100644
--- a/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/schematron/TestSvrlOutput.scala
+++ b/daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/schematron/TestSvrlOutput.scala
@@ -125,7 +125,7 @@ class TestSvrlOutput {
runCLI(args"parse --validate schematron=$conf -s $schema -r unknown") { cli =>
cli.send("12", inputDone = true)
- cli.expectErr("No root element found for unknown in any available namespace")
+ cli.expectErr("No root element found for {}unknown")
}(ExitCode.UnableToCreateProcessor)
}
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaComponent.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaComponent.scala
index d3d4adaa56..231fda8845 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaComponent.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaComponent.scala
@@ -330,19 +330,31 @@ final class Schema private (
}
/**
- * Given a name, retrieve the appropriate object.
+ * Given a qname, retrieve the appropriate object.
*
* This just scans each schema document in the schema, checking each one.
*/
- def getGlobalElementDecl(name: String) = {
+ def getGlobalElementDecl(qname: RefQName): Option[GlobalElementDecl] = {
val sds = schemaDocuments
val res = sds.flatMap { sd =>
{
- val ged = sd.getGlobalElementDecl(name)
+ val ged = sd.getGlobalElementDecl(qname)
ged
}
}
- noneOrOne(res, name)
+ noneOrOne(res, qname.toString)
+ }
+
+ def searchGlobalElementDecl(ncName: String): Seq[GlobalElementDecl] = {
+ Assert.invariant(!ncName.contains(":"))
+ val sds = schemaDocuments
+ val res = sds.flatMap { sd =>
+ {
+ val ged = sd.searchGlobalElementDecl(ncName)
+ ged
+ }
+ }
+ res
}
def getGlobalSimpleTypeDef(name: String) =
noneOrOne(schemaDocuments.flatMap { _.getGlobalSimpleTypeDef(name) }, name)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaDocument.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaDocument.scala
index 85f8c4f75d..63675fcb9f 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaDocument.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaDocument.scala
@@ -22,6 +22,7 @@ import scala.xml.Node
import org.apache.daffodil.core.dsom.IIUtils.IIMap
import org.apache.daffodil.lib.api.WarnID
import org.apache.daffodil.lib.exceptions.Assert
+import org.apache.daffodil.lib.xml.RefQName
import org.apache.daffodil.lib.xml.XMLUtils
/**
@@ -261,9 +262,16 @@ final class SchemaDocument private (xmlSDoc: XMLSchemaDocument)
lazy val defineVariables = annotationObjs.collect { case dv: DFDLDefineVariable => dv }
/**
- * by name getters for the global things that can be referenced.
+ * by name/qname getters for the global things that can be referenced.
*/
- def getGlobalElementDecl(name: String) = globalElementDecls.find { _.name == name }
+ def getGlobalElementDecl(qname: RefQName): Option[GlobalElementDecl] =
+ globalElementDecls.find {
+ _.namedQName.toRefQName == qname
+ }
+ def searchGlobalElementDecl(name: String): Seq[GlobalElementDecl] =
+ globalElementDecls.filter {
+ _.name == name
+ }
def getGlobalSimpleTypeDef(name: String) = globalSimpleTypeDefs.find { _.name == name }
def getGlobalComplexTypeDef(name: String) = globalComplexTypeDefs.find { _.name == name }
def getGlobalGroupDef(name: String) = globalGroupDefs.find { _.name == name }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala
index 792b730ead..71dab86bf4 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala
@@ -315,19 +315,19 @@ final class SchemaSet private (
* root element name, then this searches for a single element having that name, and if it is
* unambiguous, it is used as the root.
*/
- private def findRootElement(name: String) = {
+ private def findRootElement(qname: RefQName): GlobalElementDecl = {
val candidates = schemas.flatMap {
- _.getGlobalElementDecl(name)
+ _.getGlobalElementDecl(qname)
}
schemaDefinitionUnless(
candidates.length != 0,
- "No root element found for %s in any available namespace",
- name
+ "No root element found for %s",
+ qname
)
schemaDefinitionUnless(
candidates.length <= 1,
"Root element %s is ambiguous. Candidates are %s.",
- name,
+ qname,
candidates.map { gef =>
{
val tns = gef.schemaDocument.targetNamespace
@@ -356,7 +356,20 @@ final class SchemaSet private (
ge
}
case RootSpec(None, rootElementName) => {
- findRootElement(rootElementName)
+ val possibleRoots: Seq[GlobalElementDecl] = schemaSet.schemas.flatMap {
+ _.searchGlobalElementDecl(rootElementName)
+ }
+ if (possibleRoots.length == 1) {
+ possibleRoots.head
+ } else {
+ // we're here because it's ambiguous what root element to return, and
+ // no namespace URI was provided. So we assume not specifying a namespace
+ // URI may mean the intention was to choose the root that it is in No Namespace.
+ // If there is no such, then the diagnostic will encourage user to specify
+ // the namespace explicitly.
+ val qn = RefQName(None, rootElementName, NoNamespace)
+ findRootElement(qn)
+ }
}
case _ => Assert.impossible()
}
@@ -412,7 +425,7 @@ final class SchemaSet private (
*/
def getGlobalElementDecl(refQName: RefQName): Option[GlobalElementDecl] = {
getSchema(refQName.namespace).flatMap {
- _.getGlobalElementDecl(refQName.local)
+ _.getGlobalElementDecl(refQName)
}
}
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/core/util/TestUtils.scala b/daffodil-core/src/test/scala/org/apache/daffodil/core/util/TestUtils.scala
index 39495e1adb..b01fca1630 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/core/util/TestUtils.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/core/util/TestUtils.scala
@@ -386,10 +386,10 @@ class Fakes private () {
lazy val xsd_sset: SchemaSet = SchemaSet(sch, "http://example.com", "fake")
lazy val xsd_schema = xsd_sset.getSchema(NS("http://example.com")).get
lazy val fakeSD = xsd_schema.schemaDocuments(0)
- lazy val fakeElem = fakeSD.getGlobalElementDecl("fake").get
+ lazy val fakeElem = fakeSD.searchGlobalElementDecl("fake").head
lazy val fakeCT =
- fakeSD.getGlobalElementDecl("fake2").get.typeDef.asInstanceOf[GlobalComplexTypeDef]
+ fakeSD.searchGlobalElementDecl("fake2").head.typeDef.asInstanceOf[GlobalComplexTypeDef]
lazy val fakeSequence = fakeCT.sequence
lazy val Seq(fs1, fs2, fs3) = fakeSequence.groupMembers
lazy val fakeChoiceGroupRef = fs1.asInstanceOf[ChoiceGroupRef]
diff --git a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
index ad25deacf6..3a37895d31 100644
--- a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
+++ b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
@@ -695,12 +695,12 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: DFDLTestSuite) {
}
def getRootNamespaceString() = {
- if (optExpectedOrInputInfoset.isDefined)
+ if (this.rootNSAttrib != "")
+ rootNSAttrib
+ else if (optExpectedOrInputInfoset.isDefined)
infosetRootNamespaceString
else if (optEmbeddedSchema.isDefined)
XMLUtils.EXAMPLE_NAMESPACE.toString
- else if (this.rootNSAttrib != "")
- rootNSAttrib
else {
// For some TDML Processors, we have to provide
// the root namespace. They don't provide a way to search
diff --git a/daffodil-tdml-processor/src/test/resources/test/tdml/chameleon-schema1.dfdl.xsd b/daffodil-tdml-processor/src/test/resources/test/tdml/chameleon-schema1.dfdl.xsd
new file mode 100644
index 0000000000..1ef318e372
--- /dev/null
+++ b/daffodil-tdml-processor/src/test/resources/test/tdml/chameleon-schema1.dfdl.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/daffodil-tdml-processor/src/test/resources/test/tdml/generic-schema1.dfdl.xsd b/daffodil-tdml-processor/src/test/resources/test/tdml/generic-schema1.dfdl.xsd
new file mode 100644
index 0000000000..7b83031ae5
--- /dev/null
+++ b/daffodil-tdml-processor/src/test/resources/test/tdml/generic-schema1.dfdl.xsd
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala
index 691e299249..bbaceeb9f6 100644
--- a/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala
+++ b/daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala
@@ -608,4 +608,80 @@ abc # a comment
@Test def test_apos_test1(): Unit = { runner.runOneTest("apos_test1") }
@Test def test_apos_test2(): Unit = { runner.runOneTest("apos_test2") }
+ // DFDL-2947
+ @Test def test_rootNSSpecifiesNoNamespaceRoot(): Unit = {
+ val tdmlTestSuite =
+
+
+ 37
+
+
+ 37
+
+
+
+
+
+ val runner = new Runner(tdmlTestSuite)
+ runner.runOneTest("test1")
+ }
+
+ @Test def test_rootNSSpecifiesNamespaceRoot(): Unit = {
+ val tdmlTestSuite =
+
+
+ boy
+
+
+ boy
+
+
+
+
+
+ val runner = new Runner(tdmlTestSuite)
+ runner.runOneTest("test1")
+ }
+
+ @Test def test_noRootCandidates1(): Unit = {
+ val tdmlTestSuite =
+
+
+ 37
+
+ Schema Definition Error
+ no root element found
+ data1
+
+
+
+
+ val runner = new Runner(tdmlTestSuite)
+ runner.runOneTest("test1")
+ }
+
+ @Test def test_noRootCandidates2(): Unit = {
+ val tdmlTestSuite =
+
+
+ 37
+
+ Schema Definition Error
+ no global element found
+ {"{doesNotExist}"}data
+
+
+
+
+ val runner = new Runner(tdmlTestSuite)
+ runner.runOneTest("test1")
+ }
}
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/namespaces.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/namespaces.tdml
index 47c40bb3ad..2345228cf9 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/namespaces.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/namespaces.tdml
@@ -910,7 +910,7 @@
Schema Definition Error
- More than one definition for name: vagueEle
+ More than one definition for name: {}vagueElem