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) < 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"),