This is an automated email from the ASF dual-hosted git repository.

jw3 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git


The following commit(s) were added to refs/heads/master by this push:
     new 583a91d  Support embedding Schematron rules in DFDL schemas.
583a91d is described below

commit 583a91d427ee6f055e2c1957e493452d837e25c3
Author: John Wass <[email protected]>
AuthorDate: Wed Jan 20 07:18:39 2021 -0500

    Support embedding Schematron rules in DFDL schemas.
    
    DAFFODIL-2446
---
 LICENSE                                            |  63 ++++++---
 build.sbt                                          |   2 +-
 daffodil-cli/bin.LICENSE                           |  75 +++++++----
 .../org/apache/daffodil/CLI/input/uuid.txt         |   1 +
 .../apache/daffodil/schematron/TestEmbedded.scala  | 107 ++++++++++++++++
 .../daffodil/schematron/TestValidating.scala       |  44 +++++++
 .../org/apache/daffodil/schematron/package.scala   | 142 +++++++++++++++++++++
 .../src/main/scala/org/apache/daffodil/Main.scala  |   8 +-
 .../daffodil/dsom/AnnotatedSchemaComponent.scala   |  11 +-
 daffodil-schematron/README.md                      |  16 ++-
 .../src/main/resources/META-INF/LICENSE            |  75 +++++++----
 .../iso-schematron-xslt2/ExtractSchFromXSD-2.xsl   | 113 ++++++++++++++++
 .../schematron/ClassPathUriResolver.scala          |  12 +-
 .../validation/schematron/Schematron.scala         |  20 +--
 .../schematron/SchematronValidatorFactory.scala    |  29 ++---
 .../validation/schematron/Transforms.scala         |  59 +++++++++
 .../src/test/resources/sch/always-fails.sch        |  31 +++++
 .../src/test/resources/sch/never-fails.sch         |  31 +++++
 .../src/test/resources/xml/embedded-1.xml          |  19 +++
 .../src/test/resources/xsd/always-fails-1.dfdl.xsd |  41 ++++++
 .../src/test/resources/xsd/embedded-1.dfdl.xsd     |  50 ++++++++
 .../src/test/resources/xsd/embedded-2.dfdl.xsd     |  57 +++++++++
 .../src/test/resources/xsd/embedded-3.dfdl.xsd     |  91 +++++++++++++
 .../src/test/resources/xsd/extends-1.dfdl.xsd      |  59 +++++++++
 .../src/test/resources/xsd/never-fails-1.dfdl.xsd  |  42 ++++++
 .../test/resources/xsd/string.dfdl.xsd}            |  44 ++-----
 .../src/test/resources/xsd/unit_price.dfdl.xsd     |  85 ++++++++++++
 .../src/test/resources/xsd/uuid.dfdl.xsd           |  39 ++++++
 .../src/test/resources/xsd/with-ns-1.dfdl.xsd      |  53 ++++++++
 .../src/test/resources/xsd/without-ns-1.dfdl.xsd   |  48 +++++++
 .../validation/schematron/EmbeddedTesting.scala    |  90 +++++++++++++
 .../schematron/TestBasicValidation.scala           |  13 +-
 .../schematron/TestEmbeddedSchematron.scala        |  73 +++++++++++
 .../MissingAppinfoSourceNonDfdl.dfdl.xsd           |  51 +++-----
 .../SchemaDefinitionErrors.tdml                    |  20 +++
 .../schema_definition_errors/TestSDE.scala         |   1 +
 project/Rat.scala                                  |   1 +
 37 files changed, 1529 insertions(+), 187 deletions(-)

diff --git a/LICENSE b/LICENSE
index c5c01e6..04cc280 100644
--- a/LICENSE
+++ b/LICENSE
@@ -366,22 +366,47 @@ subcomponents is subject to the terms and conditions of 
the following licenses.
     - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/sch-messages-en.xhtml
   The content is available under the MIT License:
 
-  Copyright (c) 2004-2010 Rick Jellife and Academia Sinica Computing Centre, 
Taiwan
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be included in 
all
-  copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-  SOFTWARE.
+    Copyright (c) 2004-2010 Rick Jellife and Academia Sinica Computing Centre, 
Taiwan
+
+    Permission is hereby granted, free of charge, to any person obtaining a 
copy
+    of this software and associated documentation files (the "Software"), to 
deal
+    in the Software without restriction, including without limitation the 
rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in 
all
+    copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE
+    SOFTWARE.
+
+    This product bundles content from the Schematron converters, including
+    the following files:
+      - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/ExtractSchFromXSD-2.xsl
+    The content is available under the MIT License:
+
+    Copyright (c) 2002-2010 Rick Jelliffe and Topologi Pty. Ltd.
+
+    Permission is hereby granted, free of charge, to any person obtaining a 
copy
+    of this software and associated documentation files (the "Software"), to 
deal
+    in the Software without restriction, including without limitation the 
rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
diff --git a/build.sbt b/build.sbt
index 35c436c..0dea491 100644
--- a/build.sbt
+++ b/build.sbt
@@ -76,7 +76,7 @@ lazy val udf              = Project("daffodil-udf", 
file("daffodil-udf")).config
                               .settings(commonSettings)
 
 lazy val schematron       = Project("daffodil-schematron", 
file("daffodil-schematron"))
-                              .dependsOn(lib)
+                              .dependsOn(lib, sapi % Test)
                               .settings(commonSettings)
                               .settings(libraryDependencies ++= 
Dependencies.schematron)
                               .configs(IntegrationTest)
diff --git a/daffodil-cli/bin.LICENSE b/daffodil-cli/bin.LICENSE
index 161105a..2fcd1e0 100644
--- a/daffodil-cli/bin.LICENSE
+++ b/daffodil-cli/bin.LICENSE
@@ -849,30 +849,55 @@ subcomponents is subject to the terms and conditions of 
the following licenses.
 
   This product bundles content from the Schematron "skeleton" - XSLT 
implementation, including
   the following files:
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_abstract_expand.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_dsdl_include.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_schematron_message_xslt2.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_schematron_skeleton_for_saxon.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_svrl_for_xslt2.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/sch-messages-en.xhtml
+    - iso-schematron-xslt2/iso_abstract_expand.xsl in 
lib/org.apache.daffodil.daffodil-schematron-<VERSION>.jar
+    - iso-schematron-xslt2/iso_dsdl_include.xsl in 
lib/org.apache.daffodil.daffodil-schematron-<VERSION>.jar
+    - iso-schematron-xslt2/iso_schematron_message_xslt2.xsl in 
lib/org.apache.daffodil.daffodil-schematron-<VERSION>.jar
+    - iso-schematron-xslt2/iso_schematron_skeleton_for_saxon.xsl in 
lib/org.apache.daffodil.daffodil-schematron-<VERSION>.jar
+    - iso-schematron-xslt2/iso_svrl_for_xslt2.xsl in 
lib/org.apache.daffodil.daffodil-schematron-<VERSION>.jar
+    - iso-schematron-xslt2/sch-messages-en.xhtml in 
lib/org.apache.daffodil.daffodil-schematron-<VERSION>.jar
   The content is available under the MIT License:
 
-  Copyright (c) 2004-2010 Rick Jellife and Academia Sinica Computing Centre, 
Taiwan
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be included in 
all
-  copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-  SOFTWARE.
+    Copyright (c) 2004-2010 Rick Jellife and Academia Sinica Computing Centre, 
Taiwan
+
+    Permission is hereby granted, free of charge, to any person obtaining a 
copy
+    of this software and associated documentation files (the "Software"), to 
deal
+    in the Software without restriction, including without limitation the 
rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in 
all
+    copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE
+    SOFTWARE.
+
+  This product bundles content from the Schematron converters, including
+  the following files:
+    - iso-schematron-xslt2/ExtractSchFromXSD-2.xsl in 
lib/org.apache.daffodil.daffodil-schematron-<VERSION>.jar
+  The content is available under the MIT License:
+
+    Copyright (c) 2002-2010 Rick Jelliffe and Topologi Pty. Ltd.
+
+    Permission is hereby granted, free of charge, to any person obtaining a 
copy
+    of this software and associated documentation files (the "Software"), to 
deal
+    in the Software without restriction, including without limitation the 
rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
diff --git 
a/daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/uuid.txt 
b/daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/uuid.txt
new file mode 100644
index 0000000..692eb09
--- /dev/null
+++ b/daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/uuid.txt
@@ -0,0 +1 @@
+2f6481e6-542c-11eb-ae93-0242ac130002
\ No newline at end of file
diff --git 
a/daffodil-cli/src/it/scala/org/apache/daffodil/schematron/TestEmbedded.scala 
b/daffodil-cli/src/it/scala/org/apache/daffodil/schematron/TestEmbedded.scala
new file mode 100644
index 0000000..00dabd0
--- /dev/null
+++ 
b/daffodil-cli/src/it/scala/org/apache/daffodil/schematron/TestEmbedded.scala
@@ -0,0 +1,107 @@
+/*
+ * 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.schematron
+
+import net.sf.expectit.matcher.Matchers.sequence
+import org.junit.Test
+
+import java.util.UUID
+
+class TestEmbedded {
+  @Test def alwaysFails(): Unit = withShell(FailureErrorCode) {
+    val data = mktmp(UUID.randomUUID.toString)
+    val schema = "xsd/always-fails-1.dfdl.xsd"
+    s"parse --validate schematron={{$schema}} -s {{$schema}} $data" -> 
lineEndsWith("</always-fails>")
+  }
+
+  @Test def unitPriceWithoutValidation(): Unit = withShell() {
+    val data = mktmp("widget,monday,1,$5.00,$5.00")
+    val schema = "xsd/unit_price.dfdl.xsd"
+    s"parse -r list -s {{$schema}} $data" -> lineEndsWith("</ex:list>")
+  }
+
+  @Test def unitPriceWithValidation(): Unit = withShell(FailureErrorCode, 
JoinStdError) {
+    val data = mktmp("widget,monday,1,$5.00,$6.00")
+    val schema = "xsd/unit_price.dfdl.xsd"
+    s"parse -r list --validate schematron={{$schema}} -s {{$schema}} $data" -> 
sequence(
+      lineEndsWith("</ex:list>"),
+      anyLines(3)
+    )
+  }
+
+  @Test def unitPriceWithValidationCheckMessage(): Unit = 
withShell(FailureErrorCode, JoinStdError) {
+    val data = 
mktmp("widget,monday,5,$5.00,$25.00||gadget,tuesday,1,$10.00,$11.00")
+    val schema = "xsd/unit_price.dfdl.xsd"
+    s"parse -r list --validate schematron={{$schema}} -s {{$schema}} $data" -> 
sequence(
+      lineEndsWith("</ex:list>"),
+      lineEndsWith("[error] Validation Error: wrong unit price for gadget, 
tuesday"),
+      anyLines(2)
+    )
+  }
+
+  @Test def extends1(): Unit = withShell() {
+    val data = mktmp("bob;l;smith")
+    val schema = "xsd/extends-1.dfdl.xsd"
+    s"parse --validate schematron={{$schema}} -s {{$schema}} $data" -> 
lineEndsWith("</name>")
+  }
+
+  @Test def extends2(): Unit = withShell() {
+    val data = mktmp("ob;;smith")
+    val schema = "xsd/extends-1.dfdl.xsd"
+    s"parse --validate schematron={{$schema}} -s {{$schema}} $data" -> 
lineEndsWith("</name>")
+  }
+
+  @Test def extends3(): Unit = withShell(FailureErrorCode, JoinStdError) {
+    val data = mktmp(";;smith")
+    val schema = "xsd/extends-1.dfdl.xsd"
+    s"parse --validate schematron={{$schema}} -s {{$schema}} $data" -> 
validationError("first is blank")
+  }
+
+  @Test def extends4(): Unit = withShell(FailureErrorCode, JoinStdError) {
+    val data = mktmp("bob;l;")
+    val schema = "xsd/extends-1.dfdl.xsd"
+    s"parse --validate schematron={{$schema}} -s {{$schema}} $data" -> 
validationError("last is blank")
+  }
+
+  @Test def extends5(): Unit = withShell(FailureErrorCode, JoinStdError) {
+    val data = mktmp(";l;")
+    val schema = "xsd/extends-1.dfdl.xsd"
+    s"parse --validate schematron={{$schema}} -s {{$schema}} $data" -> 
sequence(
+      validationError("last is blank"),
+      validationError("first is blank")
+    )
+  }
+
+  @Test def testWithNs1(): Unit = withShell() {
+    val data = mktmp("0;1")
+    val schema = "xsd/with-ns-1.dfdl.xsd"
+    s"parse --validate schematron={{$schema}} -s {{$schema}} $data" -> 
lineEndsWith("</myns:interval>")
+  }
+
+  @Test def testWithNs2(): Unit = withShell(FailureErrorCode, JoinStdError) {
+    val data = mktmp("2;1")
+    val schema = "xsd/with-ns-1.dfdl.xsd"
+    s"parse --validate schematron={{$schema}} -s {{$schema}} $data" -> 
validationError()
+  }
+
+  @Test def testWithNs3(): Unit = withShell(FailureErrorCode, JoinStdError) {
+    val data = mktmp("0;0")
+    val schema = "xsd/with-ns-1.dfdl.xsd"
+    s"parse --validate schematron={{$schema}} -s {{$schema}} $data" -> 
validationError()
+  }
+}
diff --git 
a/daffodil-cli/src/it/scala/org/apache/daffodil/schematron/TestValidating.scala 
b/daffodil-cli/src/it/scala/org/apache/daffodil/schematron/TestValidating.scala
new file mode 100644
index 0000000..227ebc9
--- /dev/null
+++ 
b/daffodil-cli/src/it/scala/org/apache/daffodil/schematron/TestValidating.scala
@@ -0,0 +1,44 @@
+/*
+ * 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.schematron
+
+import org.junit.Test
+
+class TestValidating {
+  val data = "input/uuid.txt"
+  val uuid = "xsd/string.dfdl.xsd"
+  val never = "sch/never-fails.sch"
+  val always = "sch/always-fails.sch"
+
+  val alwaysResult = 
regexLine("<.+-fails>2f6481e6-542c-11eb-ae93-0242ac130002</.+-fails>")
+
+  // always fails sch, but no validate flag so it should pass
+  @Test def nonShouldPass(): Unit = withShell() {
+    s"parse -s {{$uuid}} {$data}" -> alwaysResult
+  }
+
+  // always fails sch, with validate flag should fail
+  @Test def failShouldFail(): Unit = withShell(FailureErrorCode) {
+    s"parse --validate schematron={{$always}} -s {{$uuid}} {$data}" -> 
alwaysResult
+  }
+
+  // never fails sch, with validate flag should pass
+  @Test def passShouldPass(): Unit = withShell() {
+    s"parse --validate schematron={{$never}} -s {{$uuid}} {$data}" -> 
alwaysResult
+  }
+}
diff --git 
a/daffodil-cli/src/it/scala/org/apache/daffodil/schematron/package.scala 
b/daffodil-cli/src/it/scala/org/apache/daffodil/schematron/package.scala
new file mode 100644
index 0000000..f0b36c5
--- /dev/null
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/schematron/package.scala
@@ -0,0 +1,142 @@
+/*
+ * 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
+
+import net.sf.expectit.MultiResult
+import org.apache.daffodil.CLI.Util
+import net.sf.expectit.matcher.Matchers.contains
+import net.sf.expectit.matcher.Matchers.eof
+import net.sf.expectit.matcher.Matchers.regexp
+import net.sf.expectit.matcher.Matchers.sequence
+import net.sf.expectit.Result
+import net.sf.expectit.matcher.Matcher
+import org.junit.Assert.fail
+
+import java.io.File
+import java.io.FileOutputStream
+import java.nio.file.Path
+import java.nio.file.Paths
+import scala.util.Failure
+import scala.util.Success
+import scala.util.Try
+import scala.util.matching.Regex
+
+/**
+ * Reference implementation for enhancements called for in DAFFODIL-2381, 
implemented specifically for Schematron.
+ *
+ * There are a number of bits in here that need abstracted to apply it across 
all CLI tests but it demonstrates one way
+ * to roll up the repetative operations required in the CLI tests.
+ *
+ * One less obvious schematron specific bit in these tests is the path 
resolution in the command line using mustache
+ * brackets.  There is a difference between where single and double brackets 
base the root of their paths from.  This
+ * is documented below in more detail.
+ *
+ */
+package object schematron {
+  val FailureErrorCode = 1
+  val JoinStdError = true
+
+  /**
+   * executes a command in a shell with the provided expectations and error 
code using a mustache syntax looks up files
+   * from local resources {path} or the daffodil-schematron resources {{path}}
+   * @param ec expected error code
+   * @param stderr join stderr in output
+   * @param body 2 tuple of daffodil arguments and expectation
+   */
+  def withShell[R <: Result](ec: Int = 0, stderr: Boolean = false)(body: => 
(String,  Matcher[R])): Unit = {
+    val (argstring, expectation) = body
+    val args = mustache.replaceAllIn(argstring, _ match {
+      case mustache2(p) => schPath(p)
+      case mustache1(p) => cliPath(p)
+    })
+
+    val joinStdErr = if(stderr) "2>&1" else ""
+    val cmd = Util.binPath :: args :: joinStdErr :: Nil mkString " "
+    val shell = Util.start("")
+    try {
+      shell.sendLine(cmd).expect(expectation)
+
+      val actualEc = 
shell.sendLine(echoEC).expect(matchEC).getInput.trim.split(eol).last
+      Try(actualEc.toInt) match {
+        case Success(`ec`) => // good
+        case Success(v) => fail(s"wrong ec, $v")
+        case Failure(_) => fail(s"unparseable ec, $actualEc")
+      }
+
+      shell.sendLine("exit")
+      shell.expect(eof)
+      shell.close()
+    } finally {
+      shell.close()
+    }
+  }
+
+  // two reasons for this bit of parsing indirection
+  // 1. support consuming resources from multiple projects
+  // 2. avoid doing the noisy and repetetive resolution in the unit tests
+  private val mustache = """\{{1,2}(.+?)}{1,2}""".r.unanchored
+  private val mustache1 = """\{(.+?)}""".r.unanchored
+  private val mustache2 = """\{\{(.+?)}}""".r.unanchored
+
+  private val echoEC = s"echo ${if(Util.isWindows) "%errorlevel%" else "$?"}"
+  private val matchEC = regexLine("""\d+""")
+
+  private def schPath(p: String): String = 
path(s"daffodil-schematron/src/test/resources/$p")
+  private def cliPath(p: String): String = 
path(s"daffodil-cli/src/it/resources/org/apache/daffodil/CLI/$p")
+  private def path(p: String): String = {
+    val full = Paths.get(Util.dafRoot, p).toString
+    val argfix = full.replaceAll("""\\""", "/")
+    Regex.quoteReplacement(argfix)
+  }
+
+  /**
+   * number of lines, any content on those lines
+   * @param n line count
+   * @return
+   */
+  def anyLines(n: Int): Matcher[_] = regexp(Seq.fill(n)(s".+$eol").mkString)
+
+  /**
+   * make a temp file containing the bytes
+   * @param str
+   * @return
+   */
+  def mktmp(d: Array[Byte]): Path = {
+    val f = File.createTempFile("schval", "data")
+    f.deleteOnExit()
+    val os = new FileOutputStream(f)
+    os.write(d)
+    os.close()
+    f.toPath
+  }
+  def mktmp(str: String): Path = mktmp(str.getBytes)
+
+  /**
+   * the common pattern on stderr when a validation error is hit
+   * @param txt optional additional validation error text
+   * @return matcher
+   */
+  def validationError(txt: String = ""): Matcher[MultiResult] =
+    sequence(contains(s"[error] Validation Error: $txt"), anyLines(3))
+
+  private lazy val eol = "\n"
+  def lineEndsWith(txt: String): Matcher[Result] = contains(s"$txt$eol")
+  def lineEndsWithRegex(pattern: String): Matcher[Result] = 
regexp(s"$pattern$eol")
+
+  def regexLine(pattern: String): Matcher[Result] = regexp(s"$pattern$eol")
+}
diff --git a/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala 
b/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
index f2c047b..a02b9a2 100644
--- a/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
+++ b/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
@@ -222,7 +222,7 @@ class CLIConf(arguments: Array[String]) extends 
scallop.ScallopConf(arguments)
 
   implicit def validateConverter = singleArgConverter[ValidationMode.Type]((s: 
String) => {
     import ValidatorPatterns._
-    s.toLowerCase match {
+    s match {
       case "on" => ValidationMode.Full
       case "limited" => ValidationMode.Limited
       case "off" => ValidationMode.Off
@@ -335,7 +335,7 @@ class CLIConf(arguments: Array[String]) extends 
scallop.ScallopConf(arguments)
     val path = opt[String](argName = "path", descr = "path to the node to 
create parser.")
     val parser = opt[File](short = 'P', argName = "file", descr = "use a 
previously saved parser.")
     val output = opt[String](argName = "file", descr = "write output to a 
given file. If not given or is -, output is written to stdout.")
-    val validate: ScallopOption[ValidationMode.Type] = 
opt[ValidationMode.Type](short = 'V', default = Some(ValidationMode.Off), 
argName = "mode", descr = "the validation mode. 'on', 'limited', 'off', or spi 
name.")
+    val validate: ScallopOption[ValidationMode.Type] = 
opt[ValidationMode.Type](short = 'V', default = Some(ValidationMode.Off), 
argName = "mode", descr = "the validation mode. 'on', 'limited', 'off', or a 
validator plugin name.")
     val vars = props[String]('D', keyName = "variable", valueName = "value", 
descr = "variables to be used when parsing. An optional namespace may be 
provided.")
     val tunables = props[String]('T', keyName = "tunable", valueName = 
"value", descr = "daffodil tunable to be used when parsing.")
     val config = opt[String](short = 'c', argName = "file", descr = "path to 
file containing configuration items.")
@@ -400,7 +400,7 @@ class CLIConf(arguments: Array[String]) extends 
scallop.ScallopConf(arguments)
     val threads = opt[Int](short = 't', argName = "threads", default = 
Some(1), descr = "The number of threads to use.")
     val path = opt[String](argName = "path", descr = "path to the node to 
create parser.")
     val parser = opt[File](short = 'P', argName = "file", descr = "use a 
previously saved parser.")
-    val validate: ScallopOption[ValidationMode.Type] = 
opt[ValidationMode.Type](short = 'V', default = Some(ValidationMode.Off), 
argName = "mode", descr = "the validation mode. 'on', 'limited', 'off', or spi 
name.")
+    val validate: ScallopOption[ValidationMode.Type] = 
opt[ValidationMode.Type](short = 'V', default = Some(ValidationMode.Off), 
argName = "mode", descr = "the validation mode. 'on', 'limited', 'off', or a 
validator plugin name.")
     val vars = props[String]('D', keyName = "variable", valueName = "value", 
descr = "variables to be used when processing. An optional namespace may be 
provided.")
     val tunables = props[String]('T', keyName = "tunable", valueName = 
"value", descr = "daffodil tunable to be used when processing.")
     val config = opt[String](short = 'c', argName = "file", descr = "path to 
file containing configuration items.")
@@ -450,7 +450,7 @@ class CLIConf(arguments: Array[String]) extends 
scallop.ScallopConf(arguments)
     val path = opt[String](argName = "path", descr = "path to the node to 
create parser.")
     val parser = opt[File](short = 'P', argName = "file", descr = "use a 
previously saved parser.")
     val output = opt[String](argName = "file", descr = "write output to file. 
If not given or is -, output is written to standard output.")
-    val validate: ScallopOption[ValidationMode.Type] = 
opt[ValidationMode.Type](short = 'V', default = Some(ValidationMode.Off), 
argName = "mode", descr = "the validation mode. 'on', 'limited', 'off', or spi 
name.")
+    val validate: ScallopOption[ValidationMode.Type] = 
opt[ValidationMode.Type](short = 'V', default = Some(ValidationMode.Off), 
argName = "mode", descr = "the validation mode. 'on', 'limited', 'off', or a 
validator plugin name.")
     val vars = props[String]('D', keyName = "variable", valueName = "value", 
descr = "variables to be used when unparsing. An optional namespace may be 
provided.")
     val tunables = props[String]('T', keyName = "tunable", valueName = 
"value", descr = "daffodil tunable to be used when parsing.")
     val config = opt[String](short = 'c', argName = "file", descr = "path to 
file containing configuration items.")
diff --git 
a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
 
b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
index 7c39683..2d67fd5 100644
--- 
a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
+++ 
b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
@@ -394,13 +394,20 @@ trait AnnotatedMixin { self: AnnotatedSchemaComponent =>
     ann
   }
 
+  private def isDfdlNamespace(ns: String): Boolean = ns.contains("ogf") && 
ns.contains("dfdl")
+
   lazy val dfdlAppInfos = {
     val ais = (annotationNode \ "appinfo")
     val dais = ais.filter { ai =>
       {
         ai.attribute("source") match {
           case None => {
-            this.SDW(WarnID.AppinfoNoSource, """xs:appinfo without source 
attribute. Is source="http://www.ogf.org/dfdl/"; missing?""")
+            // if a child node in the dfdl namespace exists we will provide a 
warning about using the source property
+            ai.child.flatMap(n => 
Option(n.namespace)).find(isDfdlNamespace).foreach { _ =>
+              SDW(WarnID.AppinfoNoSource,
+              """xs:appinfo without source attribute. Is 
source="http://www.ogf.org/dfdl/"; missing?"""
+              )
+            }
             false
           }
           case Some(n) => {
@@ -421,7 +428,7 @@ trait AnnotatedMixin { self: AnnotatedSchemaComponent =>
             // and getting false, where the types should have been the same.
             //
             val hasRightSource = (sourceNS =:= 
officialAppinfoSourceAttributeNS)
-            val isAcceptable = sourceNS.toString.contains("ogf") && 
sourceNS.toString.contains("dfdl")
+            val isAcceptable = isDfdlNamespace(sourceNS.toString)
             schemaDefinitionWarningWhen(WarnID.AppinfoDFDLSourceWrong, 
!hasRightSource && isAcceptable,
               "The xs:appinfo source attribute value '%s' should be '%s'.", 
sourceNS, officialAppinfoSourceAttributeNS)
             (hasRightSource || isAcceptable)
diff --git a/daffodil-schematron/README.md b/daffodil-schematron/README.md
index eb1f1d8..6da401a 100644
--- a/daffodil-schematron/README.md
+++ b/daffodil-schematron/README.md
@@ -18,13 +18,21 @@
 Schematron Validation
 ===
 
-Daffodil Validator API implementation for ISO Schematron in XSLT2
+Daffodil Validator API implementation for ISO Schematron in XSLT2.
+
+Supports standalone sch files or embedded schematron rules within the Daffodil 
schema.
 
 ### Configuration
 
-Parameters
+#### Parameters
 - `schematron`: default parameter provides path to the schematron file or 
resource
 
+#### XSLT & XPATH versions
+
+Schematron defaults to 1.0 of both XSLT and XPath.  Use 2.0 by setting 
`sch:queryBinding="xslt2"` on the schema.
+
+See version support comments in the 
[XSL](src/main/resources/iso-schematron-xslt2/iso_schematron_skeleton_for_saxon.xsl)
 for more details.
+
 ### Parse Results
 
 - `SchematronValidationError` on failed rule check
@@ -43,5 +51,7 @@ The `schematron` argument to the `--validate` flag will 
provide the schematron p
 
 ### References
 
-- [Camel Schematron 
Component](https://github.com/apache/camel/tree/4ea9e6c357371682b855d2d79655b41120331b7a/components/camel-schematron).
 - [ISO Schematron API](http://schematron.com/schematron-skeleton-api/)
+- [Query language 
support](https://github.com/Schematron/schematron/blob/2020-10-01/trunk/schematron/code/iso_schematron_skeleton_for_saxon.xsl#L120-L156)
+- [Camel Schematron 
Component](https://github.com/apache/camel/tree/4ea9e6c357371682b855d2d79655b41120331b7a/components/camel-schematron).
+- [Combining Schematron with other XML Schema 
languages](http://www.topologi.com/resources/schtrn_xsd_paper.html)
diff --git a/daffodil-schematron/src/main/resources/META-INF/LICENSE 
b/daffodil-schematron/src/main/resources/META-INF/LICENSE
index 96936b8..4c4c8e2 100644
--- a/daffodil-schematron/src/main/resources/META-INF/LICENSE
+++ b/daffodil-schematron/src/main/resources/META-INF/LICENSE
@@ -210,30 +210,55 @@ subcomponents is subject to the terms and conditions of 
the following licenses.
 
   This product bundles content from the Schematron "skeleton" - XSLT 
implementation, including
   the following files:
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_abstract_expand.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_dsdl_include.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_schematron_message_xslt2.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_schematron_skeleton_for_saxon.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_svrl_for_xslt2.xsl
-    - 
daffodil-schematron/src/main/resources/iso-schematron-xslt2/sch-messages-en.xhtml
+    - iso-schematron-xslt2/iso_abstract_expand.xsl
+    - iso-schematron-xslt2/iso_dsdl_include.xsl
+    - iso-schematron-xslt2/iso_schematron_message_xslt2.xsl
+    - iso-schematron-xslt2/iso_schematron_skeleton_for_saxon.xsl
+    - iso-schematron-xslt2/iso_svrl_for_xslt2.xsl
+    - iso-schematron-xslt2/sch-messages-en.xhtml
   The content is available under the MIT License:
 
-  Copyright (c) 2004-2010 Rick Jellife and Academia Sinica Computing Centre, 
Taiwan
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be included in 
all
-  copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-  SOFTWARE.
+    Copyright (c) 2004-2010 Rick Jellife and Academia Sinica Computing Centre, 
Taiwan
+
+    Permission is hereby granted, free of charge, to any person obtaining a 
copy
+    of this software and associated documentation files (the "Software"), to 
deal
+    in the Software without restriction, including without limitation the 
rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in 
all
+    copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE
+    SOFTWARE.
+
+    This product bundles content from the Schematron converters, including
+    the following files:
+      - iso-schematron-xslt2/ExtractSchFromXSD-2.xsl
+    The content is available under the MIT License:
+
+    Copyright (c) 2002-2010 Rick Jelliffe and Topologi Pty. Ltd.
+
+    Permission is hereby granted, free of charge, to any person obtaining a 
copy
+    of this software and associated documentation files (the "Software"), to 
deal
+    in the Software without restriction, including without limitation the 
rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
diff --git 
a/daffodil-schematron/src/main/resources/iso-schematron-xslt2/ExtractSchFromXSD-2.xsl
 
b/daffodil-schematron/src/main/resources/iso-schematron-xslt2/ExtractSchFromXSD-2.xsl
new file mode 100644
index 0000000..f856883
--- /dev/null
+++ 
b/daffodil-schematron/src/main/resources/iso-schematron-xslt2/ExtractSchFromXSD-2.xsl
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    
https://github.com/Schematron/schematron/blob/2020-10-01/trunk/converters/code/ToSchematron/ExtractSchFromXSD-2.xsl
+-->
+<!--
+    Extract embedded Schematron schemas in W3C XML Schemas schemas
+
+       For usage details, see 
http://www.topologi.com/resources/schtrn_xsd_paper.html
+
+        based on an original transform by Eddie Robertsson
+        2001/04/21      fn: added support for included schemas
+        2001/06/27      er: changed XMl Schema prefix from xsd: to xs: and 
changed to the Rec namespace
+        2010/04/14     rj: Update for ISO Schematron using xslt2       MIT 
licensed 2010-07-10
+-->
+
+<!--
+Open Source Initiative OSI - The MIT License:Licensing
+[OSI Approved License]
+
+Attribution is polite.
+
+The MIT License
+
+Copyright (c) 2002-2010 Rick Jelliffe and Topologi Pty. Ltd.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-->
+<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
+               xmlns:sch="http://purl.oclc.org/dsdl/schematron"; 
xmlns:xs="http://www.w3.org/2001/XMLSchema";>
+    <!-- Set the output to be XML with an XML declaration and use indentation 
-->
+    <xsl:output method="xml" omit-xml-declaration="no" indent="yes" 
standalone="yes"/>
+    <!-- -->
+    <!-- match schema and call recursive template to extract included schemas 
-->
+    <!-- -->
+    <xsl:template match="xs:schema">
+        <!-- call the schema definition template ... -->
+        <xsl:call-template name="gatherSchema">
+            <!-- ... with current current root as the $schemas parameter ... 
-->
+            <xsl:with-param name="schemas" select="/"/>
+            <!-- ... and any includes in the $include parameter -->
+            <xsl:with-param name="includes"
+                            select="document(/xs:schema/xs:*[self::xs:include 
or self::xs:import or self::xs:redefine]/@schemaLocation)"/>
+        </xsl:call-template>
+    </xsl:template>
+    <!-- -->
+    <!-- gather all included schemas into a single parameter variable -->
+    <!-- -->
+    <xsl:template name="gatherSchema">
+        <xsl:param name="schemas"/>
+        <xsl:param name="includes"/>
+        <xsl:choose>
+            <xsl:when test="count($schemas) &lt; count($schemas | $includes)">
+                <!-- when $includes includes something new, recurse ... -->
+                <xsl:call-template name="gatherSchema">
+                    <!-- ... with current $includes added to the $schemas 
parameter ... -->
+                    <xsl:with-param name="schemas" select="$schemas | 
$includes"/>
+                    <!-- ... and any *new* includes in the $include parameter 
-->
+                    <xsl:with-param name="includes"
+                                    
select="document($includes/xs:schema/xs:*[self::xs:include or self::xs:import 
or self::xs:redefine]/@schemaLocation)"/>
+                </xsl:call-template>
+            </xsl:when>
+            <xsl:otherwise>
+                <!-- we have the complete set of included schemas,
+                so now let's output the embedded schematron -->
+                <xsl:call-template name="output">
+                    <xsl:with-param name="schemas" select="$schemas"/>
+                </xsl:call-template>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+    <!-- -->
+    <!-- output the schematron information -->
+    <!-- -->
+    <xsl:template name="output">
+        <xsl:param name="schemas"/>
+        <!-- -->
+        <sch:schema queryBinding="xslt2">
+            <!-- get header-type elements - eg title and especially ns -->
+            <!-- title (just one) -->
+            <xsl:copy-of select="$schemas//xs:appinfo/sch:title[1]"/>
+            <!-- get remaining schematron schema children -->
+            <!-- get non-blank namespace elements, dropping duplicates -->
+            <xsl:for-each select="$schemas//xs:appinfo/sch:ns">
+                <xsl:if test="generate-id(.) =
+                                                               
generate-id($schemas//xs:appinfo/sch:ns[@prefix = current()/@prefix][1])">
+                    <xsl:copy-of select="."/>
+                </xsl:if>
+            </xsl:for-each>
+            <xsl:copy-of select="$schemas//xs:appinfo/sch:phase"/>
+            <xsl:copy-of select="$schemas//xs:appinfo/sch:pattern"/>
+            <sch:diagnostics>
+                <xsl:copy-of select="$schemas//xs:appinfo/sch:diagnostics/*"/>
+            </sch:diagnostics>
+        </sch:schema>
+    </xsl:template>
+    <!-- -->
+</xsl:transform>
diff --git 
a/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/ClassPathUriResolver.scala
 
b/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/ClassPathUriResolver.scala
index 467b5bb..7b63e31 100644
--- 
a/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/ClassPathUriResolver.scala
+++ 
b/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/ClassPathUriResolver.scala
@@ -31,9 +31,15 @@ final class ClassPathUriResolver(rulesDir: String, fallback: 
Option[URIResolver]
     Option(getClass.getClassLoader.getResourceAsStream(path)) match {
       case Some(is) => new StreamSource(is)
       case None =>
-        fallback.map(_.resolve(href, base)).getOrElse(
-          throw ValidatorInitializationException(s"schematron resource not 
found at $path")
-        )
+        // fallback #1;; try the raw classpath without the prefix
+        Option(getClass.getClassLoader.getResourceAsStream(href)) match {
+          case Some(is) => new StreamSource(is)
+          case None =>
+            // fallback #2;; use the fallback resolver if provided
+            fallback.map(_.resolve(href, base)).getOrElse(
+              throw ValidatorInitializationException(s"schematron resource not 
found at $path")
+            )
+        }
     }
   }
 }
diff --git 
a/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/Schematron.scala
 
b/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/Schematron.scala
index ad21e30..456e3a2 100644
--- 
a/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/Schematron.scala
+++ 
b/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/Schematron.scala
@@ -22,15 +22,10 @@ import java.io.StringWriter
 
 import javax.xml.parsers.ParserConfigurationException
 import javax.xml.parsers.SAXParserFactory
-import javax.xml.transform.Source
 import javax.xml.transform.Templates
-import javax.xml.transform.TransformerFactory
 import javax.xml.transform.URIResolver
-import javax.xml.transform.dom.DOMResult
-import javax.xml.transform.dom.DOMSource
 import javax.xml.transform.sax.SAXSource
 import javax.xml.transform.stream.StreamResult
-import javax.xml.transform.stream.StreamSource
 import org.apache.daffodil.api.ValidatorInitializationException
 import org.xml.sax.InputSource
 import org.xml.sax.SAXException
@@ -42,9 +37,6 @@ import org.xml.sax.XMLReader
  */
 object Schematron {
   val templatesRootDir = "iso-schematron-xslt2"
-  private val templatesPipeline = Array("iso_dsdl_include.xsl",
-                                        "iso_abstract_expand.xsl",
-                                        "iso_svrl_for_xslt2.xsl")
 
   private val featuress = Array(
     Feature.on(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING),
@@ -54,17 +46,7 @@ object Schematron {
 
   def fromRules(rules: Templates) = new Schematron(xmlReader.get(), rules)
 
-  def templatesFor(sch: InputStream, tf: TransformerFactory): Templates = 
tf.newTemplates(
-    templatesPipeline.foldLeft(new StreamSource(sch): Source) {
-      (source, template) =>
-        val xsl = 
getClass.getClassLoader.getResourceAsStream(s"$templatesRootDir/$template")
-        val result: DOMResult = new DOMResult
-        tf.newTransformer(new StreamSource(xsl)).transform(source, result)
-        new DOMSource(result.getNode)
-    }
-  )
-
-  def isoTemplateResolver(child: Option[URIResolver]) = new 
ClassPathUriResolver(Schematron.templatesRootDir, child)
+  def isoTemplateResolver(child: Option[URIResolver]) = new 
ClassPathUriResolver(templatesRootDir, child)
 
   // reduce overhead by caching the xml reader, but the SAXParser class is not 
thread safe so use a thread local
   private val xmlReader = new ThreadLocal[XMLReader] {
diff --git 
a/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/SchematronValidatorFactory.scala
 
b/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/SchematronValidatorFactory.scala
index 07f07df..61aba2d 100644
--- 
a/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/SchematronValidatorFactory.scala
+++ 
b/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/SchematronValidatorFactory.scala
@@ -20,14 +20,16 @@ package org.apache.daffodil.validation.schematron
 import java.io.FileInputStream
 import java.io.InputStream
 import java.nio.file.Paths
-
 import com.typesafe.config.Config
+
 import javax.xml.transform.URIResolver
 import net.sf.saxon.TransformerFactoryImpl
 import org.apache.daffodil.api.Validator
 import org.apache.daffodil.api.ValidatorFactory
 import org.apache.daffodil.api.ValidatorInitializationException
 
+import java.nio.file.Files
+
 /**
  * Daffodil ValidatorFactory implementation for ISO schematron
  */
@@ -37,28 +39,17 @@ object SchematronValidatorFactory {
       throw ValidatorInitializationException("invalid configuration: missing 
schematron path")
 
     val schPath = Paths.get(config.getString(SchematronValidator.name))
-    val schStream = if(schPath.isAbsolute) {
-        val schFile = schPath.toFile
-        if (!schFile.exists())
-          throw ValidatorInitializationException(s"file not found: schematron 
$schFile")
-        new FileInputStream(schPath.toFile)
-      }
-      else {
-      val res = getClass.getClassLoader.getResourceAsStream(schPath.toString)
-      if(res == null) {
-        throw ValidatorInitializationException(s"resource not found at 
$schPath")
-      }
-      res
-    }
-
-    makeValidator(schStream, None)
+    val schStream = if(Files.exists(schPath)) new 
FileInputStream(schPath.toFile)
+    else 
Option(getClass.getClassLoader.getResourceAsStream(schPath.toString)).getOrElse(
+      throw ValidatorInitializationException(s"schematron resource not found: 
$schPath")
+    )
+    makeValidator(schStream, SchSource.from(schPath), None)
   }
 
-  def makeValidator(schematron: InputStream, fallback: Option[URIResolver] = 
None): SchematronValidator = {
+  def makeValidator(schematron: InputStream, srcfmt: SchSource, fallback: 
Option[URIResolver] = None): SchematronValidator = {
     val factory = new TransformerFactoryImpl()
     factory.setURIResolver(Schematron.isoTemplateResolver(fallback))
-
-    val rules = Schematron.templatesFor(schematron, factory)
+    val rules = Transforms.from(schematron, srcfmt, factory)
     new SchematronValidator(Schematron.fromRules(rules))
   }
 }
diff --git 
a/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/Transforms.scala
 
b/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/Transforms.scala
new file mode 100644
index 0000000..92ccfbb
--- /dev/null
+++ 
b/daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/Transforms.scala
@@ -0,0 +1,59 @@
+/*
+ * 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.validation.schematron
+
+import javax.xml.transform.dom.DOMResult
+import javax.xml.transform.dom.DOMSource
+import java.io.InputStream
+import javax.xml.transform.Source
+import javax.xml.transform.Templates
+import javax.xml.transform.stream.StreamSource
+import javax.xml.transform.TransformerFactory
+import org.apache.daffodil.validation.schematron.Schematron.templatesRootDir
+
+import java.nio.file.Path
+
+object Transforms {
+  def from(sch: InputStream, srcfmt: SchSource, tf: TransformerFactory): 
Templates = read(sch, srcfmt.stages, tf)
+
+  private def read(sch: InputStream, stages: Seq[String], tf: 
TransformerFactory): Templates = tf.newTemplates(
+    stages.foldLeft(new StreamSource(sch): Source) { (source, template) =>
+      val xsl = 
getClass.getClassLoader.getResourceAsStream(s"$templatesRootDir/$template")
+      val result: DOMResult = new DOMResult
+      tf.newTransformer(new StreamSource(xsl)).transform(source, result)
+      new DOMSource(result.getNode)
+    }
+  )
+}
+
+sealed trait SchSource {
+  def stages: Seq[String]
+}
+object SchSource {
+  def from(p: Path): SchSource = p.getFileName.toString.split("\\.").last 
match {
+    case "sch" => Sch
+    case _ => Xsd
+  }
+
+  case object Sch extends SchSource {
+    lazy val stages = List("iso_dsdl_include.xsl", "iso_abstract_expand.xsl", 
"iso_svrl_for_xslt2.xsl")
+  }
+  case object Xsd extends SchSource {
+    lazy val stages: Seq[String] = "ExtractSchFromXSD-2.xsl" :: Sch.stages
+  }
+}
diff --git a/daffodil-schematron/src/test/resources/sch/always-fails.sch 
b/daffodil-schematron/src/test/resources/sch/always-fails.sch
new file mode 100644
index 0000000..8711c84
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/sch/always-fails.sch
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron";
+            queryBinding="xslt2">
+
+    <sch:title>Sample Schematron using XPath 2.0</sch:title>
+    <sch:ns prefix="xs" uri="http://www.w3.org/2001/XMLSchema"/>
+    <sch:ns prefix="p" uri="http://www.apache.org/camel/schematron"/>
+
+    <sch:pattern>
+        <sch:rule context=".">
+            <sch:assert test="false()">never fails</sch:assert>
+        </sch:rule>
+    </sch:pattern>
+
+</sch:schema>
diff --git a/daffodil-schematron/src/test/resources/sch/never-fails.sch 
b/daffodil-schematron/src/test/resources/sch/never-fails.sch
new file mode 100644
index 0000000..28abf88
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/sch/never-fails.sch
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron";
+            queryBinding="xslt2">
+
+    <sch:title>Sample Schematron using XPath 2.0</sch:title>
+    <sch:ns prefix="xs" uri="http://www.w3.org/2001/XMLSchema"/>
+    <sch:ns prefix="p" uri="http://www.apache.org/camel/schematron"/>
+
+    <sch:pattern>
+        <sch:rule context=".">
+            <sch:assert test="true()">always fails</sch:assert>
+        </sch:rule>
+    </sch:pattern>
+
+</sch:schema>
diff --git a/daffodil-schematron/src/test/resources/xml/embedded-1.xml 
b/daffodil-schematron/src/test/resources/xml/embedded-1.xml
new file mode 100644
index 0000000..fd59d99
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xml/embedded-1.xml
@@ -0,0 +1,19 @@
+<!--
+  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.
+-->
+<e1>
+    <uuid>7c50643e-2df3-11eb-adc1-0242ac120002</uuid>
+</e1>
diff --git a/daffodil-schematron/src/test/resources/xsd/always-fails-1.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/always-fails-1.dfdl.xsd
new file mode 100644
index 0000000..639b2ae
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/always-fails-1.dfdl.xsd
@@ -0,0 +1,41 @@
+<?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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:sch="http://purl.oclc.org/dsdl/schematron";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="always-fails" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="">
+        <xs:annotation>
+            <xs:appinfo>
+                <sch:pattern>
+                    <sch:rule context=".">
+                        <sch:assert test="false()">always fails</sch:assert>
+                    </sch:rule>
+                </sch:pattern>
+            </xs:appinfo>
+        </xs:annotation>
+    </xs:element>
+
+</xs:schema>
diff --git a/daffodil-schematron/src/test/resources/xsd/embedded-1.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/embedded-1.dfdl.xsd
new file mode 100644
index 0000000..b0dccaa
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/embedded-1.dfdl.xsd
@@ -0,0 +1,50 @@
+<?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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+        <xs:appinfo xmlns:sch="http://purl.oclc.org/dsdl/schematron";>
+            <sch:pattern name="validate-uuid">
+                <sch:rule context="uuid">
+                    <sch:assert test="string-length(time_low)=8"><sch:name/> 
wrong length</sch:assert>
+                    <sch:assert test="string-length(time_mid)=4"><sch:name/> 
wrong length</sch:assert>
+                    <sch:assert 
test="string-length(time_hi_and_version)=4"><sch:name/> wrong 
length</sch:assert>
+                    <sch:assert 
test="string-length(clock_seq_hi_and_res)=4"><sch:name/> wrong 
length</sch:assert>
+                    <sch:assert test="string-length(node)=12"><sch:name/> 
wrong length</sch:assert>
+                </sch:rule>
+            </sch:pattern>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="uuid">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="time_low" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="time_mid" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="time_hi_and_version" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="clock_seq_hi_and_res" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="node" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="" />
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+</xs:schema>
diff --git a/daffodil-schematron/src/test/resources/xsd/embedded-2.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/embedded-2.dfdl.xsd
new file mode 100644
index 0000000..df873c7
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/embedded-2.dfdl.xsd
@@ -0,0 +1,57 @@
+<?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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:sch="http://purl.oclc.org/dsdl/schematron";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo>
+            <sch:ns prefix="ex" uri="http://example.com"/>
+        </xs:appinfo>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="uuid">
+        <xs:annotation>
+            <xs:appinfo xmlns:sch="http://purl.oclc.org/dsdl/schematron";>
+                <sch:pattern name="validate-uuid">
+                    <sch:rule context="uuid">
+                        <sch:assert 
test="string-length(time_low)=8"><sch:name/> wrong length</sch:assert>
+                        <sch:assert 
test="string-length(time_mid)=4"><sch:name/> wrong length</sch:assert>
+                        <sch:assert 
test="string-length(time_hi_and_version)=4"><sch:name/> wrong 
length</sch:assert>
+                        <sch:assert 
test="string-length(clock_seq_hi_and_res)=4"><sch:name/> wrong 
length</sch:assert>
+                        <sch:assert test="string-length(node)=12"><sch:name/> 
wrong length</sch:assert>
+                    </sch:rule>
+                </sch:pattern>
+            </xs:appinfo>
+        </xs:annotation>
+
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="time_low" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="time_mid" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="time_hi_and_version" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="clock_seq_hi_and_res" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="node" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="" />
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+</xs:schema>
diff --git a/daffodil-schematron/src/test/resources/xsd/embedded-3.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/embedded-3.dfdl.xsd
new file mode 100644
index 0000000..95aec09
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/embedded-3.dfdl.xsd
@@ -0,0 +1,91 @@
+<?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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:sch="http://purl.oclc.org/dsdl/schematron";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="uuid">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="time_low" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-">
+                    <xs:annotation>
+                        <xs:appinfo>
+                            <sch:pattern>
+                                <sch:rule context="time_low">
+                                    <sch:assert 
test="string-length(.)=8"><sch:name/> wrong length</sch:assert>
+                                </sch:rule>
+                            </sch:pattern>
+                        </xs:appinfo>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="time_mid" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-">
+                    <xs:annotation>
+                        <xs:appinfo>
+                            <sch:pattern>
+                                <sch:rule context="time_mid">
+                                    <sch:assert 
test="string-length(.)=4"><sch:name/> wrong length</sch:assert>
+                                </sch:rule>
+                            </sch:pattern>
+                        </xs:appinfo>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="time_hi_and_version" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-">
+                    <xs:annotation>
+                        <xs:appinfo>
+                            <sch:pattern>
+                                <sch:rule context="time_hi_and_version">
+                                    <sch:assert 
test="string-length(.)=4"><sch:name/> wrong length</sch:assert>
+                                </sch:rule>
+                            </sch:pattern>
+                        </xs:appinfo>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="clock_seq_hi_and_res" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-">
+                    <xs:annotation>
+                        <xs:appinfo>
+                            <sch:pattern>
+                                <sch:rule context="clock_seq_hi_and_res">
+                                    <sch:assert 
test="string-length(.)=4"><sch:name/> wrong length</sch:assert>
+                                </sch:rule>
+                            </sch:pattern>
+                        </xs:appinfo>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="node" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="">
+                    <xs:annotation>
+                        <xs:appinfo>
+                            <sch:pattern>
+                                <sch:rule context="node">
+                                    <sch:assert 
test="string-length(.)=12"><sch:name/> wrong length</sch:assert>
+                                </sch:rule>
+                            </sch:pattern>
+                        </xs:appinfo>
+                    </xs:annotation>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
diff --git a/daffodil-schematron/src/test/resources/xsd/extends-1.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/extends-1.dfdl.xsd
new file mode 100644
index 0000000..91eac88
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/extends-1.dfdl.xsd
@@ -0,0 +1,59 @@
+<?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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:sch="http://purl.oclc.org/dsdl/schematron";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+        <xs:appinfo>
+            <sch:pattern>
+                <sch:rule abstract="true" id="blank">
+                    <sch:assert test="string-length(.) > 0"><sch:name/> is 
blank.</sch:assert>
+                </sch:rule>
+            </sch:pattern>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="name">
+        <xs:annotation>
+            <xs:appinfo>
+                <sch:pattern>
+                    <sch:rule context="first">
+                        <sch:extends rule="blank"/>
+                    </sch:rule>
+                    <sch:rule context="last">
+                        <sch:extends rule="blank"/>
+                    </sch:rule>
+                </sch:pattern>
+            </xs:appinfo>
+        </xs:annotation>
+
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="first" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator=";"/>
+                <xs:element name="middle" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator=";"/>
+                <xs:element name="last" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator=""/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
diff --git a/daffodil-schematron/src/test/resources/xsd/never-fails-1.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/never-fails-1.dfdl.xsd
new file mode 100644
index 0000000..0f9ef8e
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/never-fails-1.dfdl.xsd
@@ -0,0 +1,42 @@
+<?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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:sch="http://purl.oclc.org/dsdl/schematron";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+
+    <xs:element name="never-fails" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="">
+        <xs:annotation>
+            <xs:appinfo>
+                <sch:pattern>
+                    <sch:rule context=".">
+                        <sch:assert test="true()">never fails</sch:assert>
+                    </sch:rule>
+                </sch:pattern>
+            </xs:appinfo>
+        </xs:annotation>
+    </xs:element>
+
+</xs:schema>
diff --git a/daffodil-schematron/README.md 
b/daffodil-schematron/src/test/resources/xsd/string.dfdl.xsd
similarity index 50%
copy from daffodil-schematron/README.md
copy to daffodil-schematron/src/test/resources/xsd/string.dfdl.xsd
index eb1f1d8..627e671 100644
--- a/daffodil-schematron/README.md
+++ b/daffodil-schematron/src/test/resources/xsd/string.dfdl.xsd
@@ -1,3 +1,4 @@
+<?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
@@ -14,34 +15,15 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-
-Schematron Validation
-===
-
-Daffodil Validator API implementation for ISO Schematron in XSLT2
-
-### Configuration
-
-Parameters
-- `schematron`: default parameter provides path to the schematron file or 
resource
-
-### Parse Results
-
-- `SchematronValidationError` on failed rule check
-
-### SPI registration
-
-Registered as `schematron`  
-
-`Validators.get("schematron")`
-
-### Command Line Usage
-
-The `schematron` argument to the `--validate` flag will provide the schematron 
parameter and initiate the parsing.
-
-`daffodil parse --validate schematron=my.sch ...`
-
-### References
-
-- [Camel Schematron 
Component](https://github.com/apache/camel/tree/4ea9e6c357371682b855d2d79655b41120331b7a/components/camel-schematron).
-- [ISO Schematron API](http://schematron.com/schematron-skeleton-api/)
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="never-fails" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="" />
+</xs:schema>
diff --git a/daffodil-schematron/src/test/resources/xsd/unit_price.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/unit_price.dfdl.xsd
new file mode 100644
index 0000000..720fc7a
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/unit_price.dfdl.xsd
@@ -0,0 +1,85 @@
+<?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.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           targetNamespace="http://example.com";
+           xmlns:ex="http://example.com";
+           xmlns:sch="http://purl.oclc.org/dsdl/schematron";
+           sch:queryBinding="xslt2">
+
+    <!-- modified from 
daffodil-cli/src/it/resources/org/apache/daffodil/CLI/cli_schema_03.dfdl.xsd -->
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="ex:GeneralFormat" initiator="" terminator="" 
separator=""
+                         separatorPosition="infix" alignment="implicit" 
alignmentUnits="bits"
+                         trailingSkip="0" leadingSkip="0" textTrimKind="none" 
encoding="utf-8" byteOrder="bigEndian"
+                         occursCountKind="parsed" ignoreCase="no" 
representation="text"
+                         lengthKind="delimited" textNumberRep="standard" 
separatorSuppressionPolicy="anyEmpty"
+                         initiatedContent="no"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="description" type="xs:string"/>
+    <xs:element name="comment" type="xs:string"/>
+    <xs:element name="quantity" type="xs:int"/>
+    <xs:element name="unit_price" type="xs:float"/>
+    <xs:element name="price" type="xs:float"/>
+
+    <xs:group name="namedGroup">
+        <xs:sequence dfdl:separatorPosition="infix">
+            <xs:element ref="ex:description"/>
+            <xs:element ref="ex:comment"/>
+            <xs:element ref="ex:quantity"/>
+            <xs:element ref="ex:unit_price" dfdl:initiator="$"/>
+            <xs:element ref="ex:price" dfdl:initiator="$"/>
+        </xs:sequence>
+    </xs:group>
+
+    <xs:element name="Item" dfdl:lengthKind="implicit">
+        <xs:annotation>
+            <xs:appinfo>
+                <sch:ns prefix="ex" uri="http://example.com"/>
+                <sch:pattern>
+                    <sch:rule context="ex:price">
+                        <sch:assert test=". = ../ex:quantity * 
../ex:unit_price">wrong unit price for <sch:value-of 
select="../ex:description"/>, <sch:value-of 
select="../ex:comment"/></sch:assert>
+                    </sch:rule>
+                </sch:pattern>
+            </xs:appinfo>
+        </xs:annotation>
+
+        <xs:complexType>
+
+            <xs:group ref="ex:namedGroup" dfdl:separator=",">
+            </xs:group>
+
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="list" dfdl:lengthKind="implicit">
+        <xs:complexType>
+            <xs:sequence dfdl:separator="||"
+                         dfdl:separatorPosition="infix">
+                <xs:element ref="ex:Item" maxOccurs="unbounded" minOccurs="1"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
diff --git a/daffodil-schematron/src/test/resources/xsd/uuid.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/uuid.dfdl.xsd
new file mode 100644
index 0000000..99deae2
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/uuid.dfdl.xsd
@@ -0,0 +1,39 @@
+<?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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="uuid">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="time_low" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="time_mid" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="time_hi_and_version" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="clock_seq_hi_and_res" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="-" />
+                <xs:element name="node" type="xs:string" 
dfdl:lengthKind="delimited" dfdl:terminator="" />
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+</xs:schema>
diff --git a/daffodil-schematron/src/test/resources/xsd/with-ns-1.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/with-ns-1.dfdl.xsd
new file mode 100644
index 0000000..2264375
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/with-ns-1.dfdl.xsd
@@ -0,0 +1,53 @@
+<?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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:sch="http://purl.oclc.org/dsdl/schematron";
+           targetNamespace="http://foo.bar.com/v1";
+           xmlns:myns="http://foo.bar.com/v1";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+        <xs:appinfo>
+            <sch:ns prefix="myns" uri="http://foo.bar.com/v1"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="interval">
+        <xs:annotation>
+            <xs:appinfo>
+                <sch:pattern>
+                    <sch:rule context="myns:interval">
+                        <sch:assert test="stop > start"><sch:name/> stop must 
come after start</sch:assert>
+                    </sch:rule>
+                </sch:pattern>
+            </xs:appinfo>
+        </xs:annotation>
+
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="start" type="xs:long" 
dfdl:lengthKind="delimited" dfdl:terminator=";"/>
+                <xs:element name="stop" type="xs:long" 
dfdl:lengthKind="delimited" dfdl:terminator=""/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
diff --git a/daffodil-schematron/src/test/resources/xsd/without-ns-1.dfdl.xsd 
b/daffodil-schematron/src/test/resources/xsd/without-ns-1.dfdl.xsd
new file mode 100644
index 0000000..94dc7f7
--- /dev/null
+++ b/daffodil-schematron/src/test/resources/xsd/without-ns-1.dfdl.xsd
@@ -0,0 +1,48 @@
+<?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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+           xmlns:sch="http://purl.oclc.org/dsdl/schematron";>
+
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/";>
+            <dfdl:format ref="GeneralFormat"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="interval">
+        <xs:annotation>
+            <xs:appinfo>
+                <sch:pattern>
+                    <sch:rule context="interval">
+                        <sch:assert test="stop > start"><sch:name/> stop must 
come after start</sch:assert>
+                    </sch:rule>
+                </sch:pattern>
+            </xs:appinfo>
+        </xs:annotation>
+
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="start" type="xs:long" 
dfdl:lengthKind="delimited" dfdl:terminator=";"/>
+                <xs:element name="stop" type="xs:long" 
dfdl:lengthKind="delimited" dfdl:terminator=""/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
diff --git 
a/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/EmbeddedTesting.scala
 
b/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/EmbeddedTesting.scala
new file mode 100644
index 0000000..6a914eb
--- /dev/null
+++ 
b/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/EmbeddedTesting.scala
@@ -0,0 +1,90 @@
+/*
+ * 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.validation.schematron
+
+import org.apache.daffodil.sapi.Daffodil
+import org.apache.daffodil.sapi.DataProcessor
+import org.apache.daffodil.sapi.Diagnostic
+import org.apache.daffodil.sapi.ParseResult
+import org.apache.daffodil.sapi.infoset.XMLTextInfosetOutputter
+import org.apache.daffodil.sapi.io.InputSourceDataInputStream
+import org.apache.daffodil.util.Misc
+import org.apache.daffodil.validation.schematron.SchSource.Xsd
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.File
+
+trait EmbeddedTesting {
+  case class PR(r: ParseResult) {
+    def validated: Boolean = !r.isValidationError()
+    def diagnostics: Seq[Diagnostic] = r.getDiagnostics
+  }
+
+  sealed trait PrintInfosetMode
+  case object Quiet extends PrintInfosetMode
+  case object AnyError extends PrintInfosetMode
+  case object ValError extends PrintInfosetMode
+  case object ProcError extends PrintInfosetMode
+  case object Always extends PrintInfosetMode
+
+  case class Validation(dp: DataProcessor) {
+    def parse(str: String, verbose: PrintInfosetMode = Quiet): PR = 
withBytes(str.getBytes, verbose)
+
+    def withBytes(bytes: Array[Byte], verbose: PrintInfosetMode = Quiet): PR = 
{
+      val bos = new ByteArrayOutputStream()
+      val r1 = dp.parse(
+        new InputSourceDataInputStream(new ByteArrayInputStream(bytes)),
+        new XMLTextInfosetOutputter(bos, true))
+
+      verbose match {
+        case Always | AnyError if r1.isError() => 
r1.getDiagnostics.foreach(println)
+        case Always => println(bos.toString)
+        case ValError if r1.isValidationError() => 
r1.getDiagnostics.foreach(println)
+        case ProcError if r1.isProcessingError() => 
r1.getDiagnostics.foreach(println)
+        case _ =>
+      }
+
+      PR(r1)
+    }
+  }
+
+  def withSchema(xsd: String)(f: Validation => Unit): Unit = {
+    val schema = Misc.getRequiredResource(xsd)
+    val c = Daffodil.compiler()
+    val pf = c.compileFile(new File(schema))
+
+    if(pf.isError()) pf.getDiagnostics.foreach(println)
+    assertFalse("Schema did not compile", pf.isError())
+
+    val v = 
SchematronValidatorFactory.makeValidator(schema.toURL.openStream(), Xsd)
+    val dp = pf.onPath("/").withValidator(v)
+
+    f(Validation(dp))
+  }
+
+  def shouldPass(pr: PR): Unit = check(pr)(assertTrue)
+  def shouldFail(pr: PR): Unit = check(pr)(assertFalse)
+
+  def check(pr: PR)(f: Boolean => Unit): Unit = {
+    if (!pr.validated) pr.diagnostics.foreach(println)
+    f(pr.validated)
+  }
+}
diff --git 
a/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestBasicValidation.scala
 
b/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestBasicValidation.scala
index dff8bb5..a32acb2 100644
--- 
a/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestBasicValidation.scala
+++ 
b/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestBasicValidation.scala
@@ -18,13 +18,13 @@
 package org.apache.daffodil.validation.schematron
 
 import java.io.ByteArrayInputStream
-
 import net.sf.saxon.TransformerFactoryImpl
+import org.apache.daffodil.validation.schematron.SchSource.Sch
 import org.junit.Assert.assertNotNull
 import org.junit.Test
+
 import javax.xml.transform.URIResolver
 import javax.xml.transform.stream.StreamSource
-
 import scala.io.Source
 
 
@@ -37,7 +37,7 @@ class TestBasicValidation {
   @Test def testValidXML(): Unit = {
     val sch = Source.fromResource("sch/schematron-1.sch").mkString
     val xml = Source.fromResource("xml/article-1.xml").mkString
-    val p = SchematronValidatorFactory.makeValidator(new 
ByteArrayInputStream(sch.getBytes))
+    val p = SchematronValidatorFactory.makeValidator(new 
ByteArrayInputStream(sch.getBytes), Sch)
 
     val result = p.validateXML(new ByteArrayInputStream(xml.getBytes))
     assert(result.errors.isEmpty)
@@ -46,7 +46,7 @@ class TestBasicValidation {
   @Test def testInvalidXML(): Unit = {
     val sch = Source.fromResource("sch/schematron-2.sch").mkString
     val xml = Source.fromResource("xml/article-2.xml").mkString
-    val p = SchematronValidatorFactory.makeValidator(new 
ByteArrayInputStream(sch.getBytes))
+    val p = SchematronValidatorFactory.makeValidator(new 
ByteArrayInputStream(sch.getBytes), Sch)
 
     val result = p.validateXML(new ByteArrayInputStream(xml.getBytes))
     result.errors.forEach(e => println(s"Fail: ${e.getMessage}"))
@@ -56,7 +56,7 @@ class TestBasicValidation {
   @Test def testInvalidXML2(): Unit = {
     val sch = Source.fromResource("sch/schematron-3.sch").mkString
     val xml = Source.fromResource("xml/article-3.xml").mkString
-    val p = SchematronValidatorFactory.makeValidator(new 
ByteArrayInputStream(sch.getBytes), Some(new CustomResolver))
+    val p = SchematronValidatorFactory.makeValidator(new 
ByteArrayInputStream(sch.getBytes), Sch, Some(new CustomResolver))
 
     val result = p.validateXML(new ByteArrayInputStream(xml.getBytes))
     result.errors.forEach(e => println(s"Fail: ${e.getMessage}"))
@@ -67,7 +67,8 @@ class TestBasicValidation {
     val resolver = new ClassPathUriResolver(Schematron.templatesRootDir, None)
     val factory = new TransformerFactoryImpl()
     factory.setURIResolver(resolver)
-    val rules = 
Schematron.templatesFor(getClass.getClassLoader.getResourceAsStream("sch/schematron-1.sch"),
 factory)
+    val sch = 
getClass.getClassLoader.getResourceAsStream("sch/schematron-1.sch")
+    val rules = Transforms.from(sch, Sch, factory)
     assertNotNull(rules)
   }
 
diff --git 
a/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestEmbeddedSchematron.scala
 
b/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestEmbeddedSchematron.scala
new file mode 100644
index 0000000..1b36091
--- /dev/null
+++ 
b/daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestEmbeddedSchematron.scala
@@ -0,0 +1,73 @@
+/*
+ * 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.validation.schematron
+
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+import java.util.UUID
+
+class TestEmbeddedSchematron extends EmbeddedTesting {
+  @Test def variation1(): Unit = withSchema("xsd/embedded-1.dfdl.xsd") { f =>
+    assertTrue(f.parse(UUID.randomUUID.toString).validated)
+    assertFalse(f.parse(UUID.randomUUID.toString.drop(1)).validated)
+  }
+
+  @Test def variation2(): Unit = withSchema("xsd/embedded-2.dfdl.xsd") { f =>
+    assertTrue(f.parse(UUID.randomUUID.toString).validated)
+    assertFalse(f.parse(UUID.randomUUID.toString.drop(1)).validated)
+  }
+
+  @Test def variation3(): Unit = withSchema("xsd/embedded-3.dfdl.xsd") { f =>
+    f.parse(UUID.randomUUID.toString).diagnostics.foreach(println)
+    assertTrue(f.parse(UUID.randomUUID.toString).validated)
+    f.parse(UUID.randomUUID.toString).diagnostics.foreach(println)
+    assertFalse(f.parse(UUID.randomUUID.toString.drop(1)).validated)
+  }
+
+  @Test def testNeverFails(): Unit = withSchema("xsd/never-fails-1.dfdl.xsd") 
{ f =>
+    val good = UUID.randomUUID.toString
+    assertTrue(f.parse(good).validated)
+  }
+
+  @Test def testAlwaysFails(): Unit = 
withSchema("xsd/always-fails-1.dfdl.xsd") { f =>
+    val good = UUID.randomUUID.toString
+    assertFalse(f.parse(good).validated)
+  }
+
+  @Test def testExtends(): Unit = withSchema("xsd/extends-1.dfdl.xsd") { f =>
+    assertTrue(f.parse("bob;l;smith").validated)
+    assertTrue(f.parse("bob;;smith").validated)
+    assertFalse(f.parse(";;smith").validated)
+    assertFalse(f.parse("bob;l;").validated)
+    assertFalse(f.parse(";l;").validated)
+  }
+
+  @Test def testNoNs1(): Unit = withSchema("xsd/without-ns-1.dfdl.xsd") { f =>
+    assertTrue(f.parse("0;1", Always).validated)
+    assertFalse(f.parse("2;1").validated)
+    assertFalse(f.parse("0;0").validated)
+  }
+
+  @Test def testWithNs1(): Unit = withSchema("xsd/with-ns-1.dfdl.xsd") { f =>
+    assertTrue(f.parse("0;1", Always).validated)
+    assertFalse(f.parse("2;1").validated)
+    assertFalse(f.parse("0;0").validated)
+  }
+}
diff --git a/daffodil-schematron/README.md 
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/MissingAppinfoSourceNonDfdl.dfdl.xsd
similarity index 50%
copy from daffodil-schematron/README.md
copy to 
daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/MissingAppinfoSourceNonDfdl.dfdl.xsd
index eb1f1d8..70e2a7c 100644
--- a/daffodil-schematron/README.md
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/MissingAppinfoSourceNonDfdl.dfdl.xsd
@@ -1,3 +1,4 @@
+<?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
@@ -15,33 +16,23 @@
   limitations under the License.
 -->
 
-Schematron Validation
-===
-
-Daffodil Validator API implementation for ISO Schematron in XSLT2
-
-### Configuration
-
-Parameters
-- `schematron`: default parameter provides path to the schematron file or 
resource
-
-### Parse Results
-
-- `SchematronValidationError` on failed rule check
-
-### SPI registration
-
-Registered as `schematron`  
-
-`Validators.get("schematron")`
-
-### Command Line Usage
-
-The `schematron` argument to the `--validate` flag will provide the schematron 
parameter and initiate the parsing.
-
-`daffodil parse --validate schematron=my.sch ...`
-
-### References
-
-- [Camel Schematron 
Component](https://github.com/apache/camel/tree/4ea9e6c357371682b855d2d79655b41120331b7a/components/camel-schematron).
-- [ISO Schematron API](http://schematron.com/schematron-skeleton-api/)
+<xs:schema
+  xmlns:xs="http://www.w3.org/2001/XMLSchema";
+  xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+  xmlns:sch="http://purl.oclc.org/dsdl/schematron";
+>
+  <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/";>
+      <dfdl:format ref="GeneralFormat"/>
+    </xs:appinfo>
+  </xs:annotation>
+
+  <xs:element name="elem" type="xs:string" dfdl:lengthKind="delimited" 
dfdl:terminator="">
+    <xs:annotation>
+      <xs:appinfo>
+        <sch:title>this isnt dfdl so shouldnt get a diagnostic</sch:title>
+      </xs:appinfo>
+    </xs:annotation>
+  </xs:element>
+</xs:schema>
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
index f53d51b..b58ff01 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
@@ -192,6 +192,26 @@
   </tdml:parserTestCase>
 
 <!--
+    Test Name: missing_appinfo_source_nondfdl
+       Schema: warning
+         Root: elem
+      Purpose: This test demonstrates tdml:warnings
+-->
+
+  <tdml:parserTestCase name="missing_appinfo_source_nondfdl" root="elem"
+                       model="MissingAppinfoSourceNonDfdl.dfdl.xsd"
+                       description="">
+    <tdml:document><![CDATA[test]]></tdml:document>
+
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <elem>test</elem>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+
+  </tdml:parserTestCase>
+
+<!--
     Test Name: schema_line_number
        Schema: lineNumber.dfdl.xsd
          Root: e1
diff --git 
a/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
 
b/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
index f5b3635..901557d 100644
--- 
a/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
+++ 
b/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
@@ -43,6 +43,7 @@ class TestSDE {
   @Test def test_schema_line_number(): Unit = { 
runner.runOneTest("schema_line_number") }
   @Test def test_schema_warning(): Unit = { 
runner.runOneTest("schema_warning") }
   @Test def test_missing_appinfo_source(): Unit = { 
runner.runOneTest("missing_appinfo_source") }
+  @Test def test_missing_appinfo_source_nondfdl(): Unit = { 
runner.runOneTest("missing_appinfo_source_nondfdl") }
   @Test def test_missing_closing_tag(): Unit = { 
runner.runOneTest("missing_closing_tag") }
   @Test def test_ignoreAttributeFormDefault(): Unit = { 
runner.runOneTest("ignoreAttributeFormDefault") }
 }
diff --git a/project/Rat.scala b/project/Rat.scala
index 4c56afb..67e67c8 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -75,6 +75,7 @@ object Rat {
     
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/inputBig1M.txt"),
     
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/prefix.txt"),
     
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/test_DFDL-714.txt"),
+    
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/uuid.txt"),
     
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/output/output1.txt"),
     
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/output/output1_nopretty.txt"),
     
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/output/output2.txt"),

Reply via email to