mirror of
https://github.com/itplr-kosit/validator.git
synced 2026-05-25 16:55:39 +00:00
Resolve "Wrong Schematron/XSLTs lead to positive validation result (GitHub 165)"
This commit is contained in:
parent
155d3dc692
commit
7bd423c458
9 changed files with 417 additions and 9 deletions
|
|
@ -139,6 +139,15 @@ public class CommandlineApplicationTest {
|
|||
assertThat(CommandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidMinimalConfigurationXSLTRuntimeError() {
|
||||
final String[] args = { "-s", Paths.get(Simple.SCENARIOS_XSLT_RUNTIME_ERROR).toString(), "-h", "-o",
|
||||
this.output.toAbsolutePath().toString(), "--serialize-report-input",
|
||||
Paths.get(Simple.SIMPLE_XSLT_RUNTIME_ERROR).toString() };
|
||||
CommandLineApplication.mainProgram(args);
|
||||
assertThat(CommandLine.getErrorOutput()).contains(RESULT_OUTPUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidNamingConfiguration() {
|
||||
final String[] args = { "-s", Paths.get(Simple.SCENARIOS).toString(), "-r", Paths.get(Simple.REPOSITORY_URI).toString(),
|
||||
|
|
@ -159,7 +168,7 @@ public class CommandlineApplicationTest {
|
|||
@Test
|
||||
public void testValidDirectoryInput() {
|
||||
final String[] args = { "-s", Paths.get(Simple.SCENARIOS).toString(), "-o", this.output.toString(), "-r",
|
||||
Paths.get(Simple.REPOSITORY_URI).toString(), Paths.get(Simple.EXAMPLES).toString() };
|
||||
Paths.get(Simple.REPOSITORY_URI).toString(), Paths.get(Simple.INPUT).toString() };
|
||||
CommandLineApplication.mainProgram(args);
|
||||
assertThat(CommandLine.getErrorOutput()).contains("Processing 9 object(s) completed");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,15 +49,18 @@ public class Helper {
|
|||
|
||||
public static final URI ROOT = EXAMPLES_DIR.resolve("simple/");
|
||||
|
||||
public static final URI EXAMPLES = ROOT.resolve("input/");
|
||||
public static final URI INPUT = ROOT.resolve("input/");
|
||||
|
||||
public static final URI SIMPLE_VALID = ROOT.resolve("input/simple.xml");
|
||||
|
||||
public static final URI SIMPLE_XSLT_RUNTIME_ERROR = EXAMPLES_DIR
|
||||
.resolve("invalid/xslt-runtime-error/input/simple-xslt-runtime-error.xml");
|
||||
|
||||
public static final URI FOO = ROOT.resolve("input/foo.xml");
|
||||
|
||||
public static final URI FOO_SCHEMATRON_INVALID = EXAMPLES.resolve("foo-schematron-invalid.xml");
|
||||
public static final URI FOO_SCHEMATRON_INVALID = INPUT.resolve("foo-schematron-invalid.xml");
|
||||
|
||||
public static final URI FOO_CUSTOM_LEVEL_ERROR = EXAMPLES.resolve("foo-custom-level-error.xml");
|
||||
public static final URI FOO_CUSTOM_LEVEL_ERROR = INPUT.resolve("foo-custom-level-error.xml");
|
||||
|
||||
public static final URI REJECTED = ROOT.resolve("input/withManualReject.xml");
|
||||
|
||||
|
|
@ -65,6 +68,9 @@ public class Helper {
|
|||
|
||||
public static final URI SCENARIOS_WITH_RELATIVE_PATHS = ROOT.resolve("scenarios-with-relative-paths.xml");
|
||||
|
||||
public static final URI SCENARIOS_XSLT_RUNTIME_ERROR = EXAMPLES_DIR
|
||||
.resolve("invalid/xslt-runtime-error/scenarios-with-xslt-runtime-error.xml");
|
||||
|
||||
public static final URI OTHER_SCENARIOS = ROOT.resolve("otherScenarios.xml");
|
||||
|
||||
public static final URI ERROR_SCENARIOS = ROOT.resolve("scenarios-with-errors.xml");
|
||||
|
|
@ -101,6 +107,7 @@ public class Helper {
|
|||
|
||||
public static class Invalid {
|
||||
|
||||
// Is the typo in the name on purpose???
|
||||
public static final URI ROOT = EXAMPLES_DIR.resolve("invaid/");
|
||||
|
||||
public static final URI SCENARIOS = ROOT.resolve("scenarios.xml");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<simple xmlns="http://validator.kosit.de/test-sample">
|
||||
<inner>abc</inner>
|
||||
<inner>def</inner>
|
||||
<content>
|
||||
<IDontCare/>
|
||||
</content>
|
||||
</simple>
|
||||
<!--
|
||||
~ Copyright 2017-2026 Koordinierungsstelle für IT-Standards (KoSIT)
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:in="http://www.xoev.de/de/validator/framework/1/createreportinput"
|
||||
exclude-result-prefixes="xs"
|
||||
version="2.0">
|
||||
|
||||
<xsl:output method="xml" indent="yes" />
|
||||
|
||||
<xsl:param name="input-document" as="document-node(element())" required="yes" />
|
||||
|
||||
|
||||
<xsl:template match="in:createReportInput">
|
||||
<report xmlns="http://validator.kosit.de/test-report">
|
||||
<input>
|
||||
<xsl:copy-of select="$input-document" />
|
||||
</input>
|
||||
<result>
|
||||
<xsl:copy-of select="." />
|
||||
</result>
|
||||
<text>
|
||||
<xsl:value-of select="unparsed-text('some.txt','UTF-8')" />
|
||||
</text>
|
||||
</report>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
|
||||
<xsl:stylesheet
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:s="http://validator.kosit.de/test-sample"
|
||||
version="2.0"><!--Implementers: please note that overriding process-prolog or process-root is
|
||||
the preferred method for meta-stylesheets to use where possible. -->
|
||||
<xsl:param name="archiveDirParameter" />
|
||||
<xsl:param name="archiveNameParameter" />
|
||||
<xsl:param name="fileNameParameter" />
|
||||
<xsl:param name="fileDirParameter" />
|
||||
<xsl:variable name="document-uri">
|
||||
<xsl:value-of select="document-uri(/)" />
|
||||
</xsl:variable>
|
||||
|
||||
<!--PHASES-->
|
||||
|
||||
|
||||
<!--PROLOG-->
|
||||
<xsl:output xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
|
||||
method="xml"
|
||||
omit-xml-declaration="no"
|
||||
standalone="yes"
|
||||
indent="yes" />
|
||||
|
||||
<!--XSD TYPES FOR XSLT2-->
|
||||
|
||||
|
||||
<!--KEYS AND FUNCTIONS-->
|
||||
|
||||
|
||||
<!--DEFAULT RULES-->
|
||||
|
||||
|
||||
<!--MODE: SCHEMATRON-SELECT-FULL-PATH-->
|
||||
<!--This mode can be used to generate an ugly though full XPath for locators-->
|
||||
<xsl:template match="*" mode="schematron-select-full-path">
|
||||
<xsl:apply-templates select="." mode="schematron-get-full-path" />
|
||||
</xsl:template>
|
||||
|
||||
<!--MODE: SCHEMATRON-FULL-PATH-->
|
||||
<!--This mode can be used to generate an ugly though full XPath for locators-->
|
||||
<xsl:template match="*" mode="schematron-get-full-path">
|
||||
<xsl:apply-templates select="parent::*" mode="schematron-get-full-path" />
|
||||
<xsl:text>/</xsl:text>
|
||||
<xsl:choose>
|
||||
<xsl:when test="namespace-uri()=''">
|
||||
<xsl:value-of select="name()" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:text>*:</xsl:text>
|
||||
<xsl:value-of select="local-name()" />
|
||||
<xsl:text>[namespace-uri()='</xsl:text>
|
||||
<xsl:value-of select="namespace-uri()" />
|
||||
<xsl:text>']</xsl:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:variable name="preceding"
|
||||
select="count(preceding-sibling::*[local-name()=local-name(current()) and namespace-uri() = namespace-uri(current())])" />
|
||||
<xsl:text>[</xsl:text>
|
||||
<xsl:value-of select="1+ $preceding" />
|
||||
<xsl:text>]</xsl:text>
|
||||
</xsl:template>
|
||||
<xsl:template match="@*" mode="schematron-get-full-path">
|
||||
<xsl:apply-templates select="parent::*" mode="schematron-get-full-path" />
|
||||
<xsl:text>/</xsl:text>
|
||||
<xsl:choose>
|
||||
<xsl:when test="namespace-uri()=''">@<xsl:value-of select="name()" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:text>@*[local-name()='</xsl:text>
|
||||
<xsl:value-of select="local-name()" />
|
||||
<xsl:text>' and namespace-uri()='</xsl:text>
|
||||
<xsl:value-of select="namespace-uri()" />
|
||||
<xsl:text>']</xsl:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!--MODE: SCHEMATRON-FULL-PATH-2-->
|
||||
<!--This mode can be used to generate prefixed XPath for humans-->
|
||||
<xsl:template match="node() | @*" mode="schematron-get-full-path-2">
|
||||
<xsl:for-each select="ancestor-or-self::*">
|
||||
<xsl:text>/</xsl:text>
|
||||
<xsl:value-of select="name(.)" />
|
||||
<xsl:if test="preceding-sibling::*[name(.)=name(current())]">
|
||||
<xsl:text>[</xsl:text>
|
||||
<xsl:value-of select="count(preceding-sibling::*[name(.)=name(current())])+1" />
|
||||
<xsl:text>]</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:if test="not(self::*)">
|
||||
<xsl:text />/@<xsl:value-of select="name(.)" />
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<!--MODE: SCHEMATRON-FULL-PATH-3-->
|
||||
<!--This mode can be used to generate prefixed XPath for humans
|
||||
(Top-level element has index)-->
|
||||
<xsl:template match="node() | @*" mode="schematron-get-full-path-3">
|
||||
<xsl:for-each select="ancestor-or-self::*">
|
||||
<xsl:text>/</xsl:text>
|
||||
<xsl:value-of select="name(.)" />
|
||||
<xsl:if test="parent::*">
|
||||
<xsl:text>[</xsl:text>
|
||||
<xsl:value-of select="count(preceding-sibling::*[name(.)=name(current())])+1" />
|
||||
<xsl:text>]</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:if test="not(self::*)">
|
||||
<xsl:text />/@<xsl:value-of select="name(.)" />
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<!--MODE: GENERATE-ID-FROM-PATH -->
|
||||
<xsl:template match="/" mode="generate-id-from-path" />
|
||||
<xsl:template match="text()" mode="generate-id-from-path">
|
||||
<xsl:apply-templates select="parent::*" mode="generate-id-from-path" />
|
||||
<xsl:value-of select="concat('.text-', 1+count(preceding-sibling::text()), '-')" />
|
||||
</xsl:template>
|
||||
<xsl:template match="comment()" mode="generate-id-from-path">
|
||||
<xsl:apply-templates select="parent::*" mode="generate-id-from-path" />
|
||||
<xsl:value-of select="concat('.comment-', 1+count(preceding-sibling::comment()), '-')" />
|
||||
</xsl:template>
|
||||
<xsl:template match="processing-instruction()" mode="generate-id-from-path">
|
||||
<xsl:apply-templates select="parent::*" mode="generate-id-from-path" />
|
||||
<xsl:value-of select="concat('.processing-instruction-', 1+count(preceding-sibling::processing-instruction()), '-')" />
|
||||
</xsl:template>
|
||||
<xsl:template match="@*" mode="generate-id-from-path">
|
||||
<xsl:apply-templates select="parent::*" mode="generate-id-from-path" />
|
||||
<xsl:value-of select="concat('.@', name())" />
|
||||
</xsl:template>
|
||||
<xsl:template match="*" mode="generate-id-from-path" priority="-0.5">
|
||||
<xsl:apply-templates select="parent::*" mode="generate-id-from-path" />
|
||||
<xsl:text>.</xsl:text>
|
||||
<xsl:value-of select="concat('.',name(),'-',1+count(preceding-sibling::*[name()=name(current())]),'-')" />
|
||||
</xsl:template>
|
||||
|
||||
<!--MODE: GENERATE-ID-2 -->
|
||||
<xsl:template match="/" mode="generate-id-2">U</xsl:template>
|
||||
<xsl:template match="*" mode="generate-id-2" priority="2">
|
||||
<xsl:text>U</xsl:text>
|
||||
<xsl:number level="multiple" count="*" />
|
||||
</xsl:template>
|
||||
<xsl:template match="node()" mode="generate-id-2">
|
||||
<xsl:text>U.</xsl:text>
|
||||
<xsl:number level="multiple" count="*" />
|
||||
<xsl:text>n</xsl:text>
|
||||
<xsl:number count="node()" />
|
||||
</xsl:template>
|
||||
<xsl:template match="@*" mode="generate-id-2">
|
||||
<xsl:text>U.</xsl:text>
|
||||
<xsl:number level="multiple" count="*" />
|
||||
<xsl:text>_</xsl:text>
|
||||
<xsl:value-of select="string-length(local-name(.))" />
|
||||
<xsl:text>_</xsl:text>
|
||||
<xsl:value-of select="translate(name(),':','.')" />
|
||||
</xsl:template>
|
||||
<!--Strip characters-->
|
||||
<xsl:template match="text()" priority="-1" />
|
||||
|
||||
<!--SCHEMA SETUP-->
|
||||
<xsl:template match="/">
|
||||
<svrl:schematron-output xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
|
||||
title="Schematron Simple"
|
||||
schemaVersion="">
|
||||
<xsl:comment>
|
||||
<xsl:value-of select="$archiveDirParameter" />
|
||||
<xsl:value-of select="$archiveNameParameter" />
|
||||
<xsl:value-of select="$fileNameParameter" />
|
||||
<xsl:value-of select="$fileDirParameter" />
|
||||
</xsl:comment>
|
||||
<svrl:ns-prefix-in-attribute-values uri="http://www.w3.org/2001/XMLSchema" prefix="xs" />
|
||||
<svrl:ns-prefix-in-attribute-values uri="http://validator.kosit.de/test-sample" prefix="s" />
|
||||
<svrl:active-pattern>
|
||||
<xsl:attribute name="document">
|
||||
<xsl:value-of select="document-uri(/)" />
|
||||
</xsl:attribute>
|
||||
<xsl:apply-templates />
|
||||
</svrl:active-pattern>
|
||||
<xsl:apply-templates select="/" mode="M3" />
|
||||
</svrl:schematron-output>
|
||||
</xsl:template>
|
||||
|
||||
<!--SCHEMATRON PATTERNS-->
|
||||
<svrl:text xmlns:svrl="http://purl.oclc.org/dsdl/svrl">Schematron Simple</svrl:text>
|
||||
|
||||
<!--PATTERN -->
|
||||
|
||||
|
||||
<!--RULE -->
|
||||
<xsl:template match="s:simple" priority="1001" mode="M3">
|
||||
<svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl" context="s:simple" />
|
||||
|
||||
<!--ASSERT -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="xs:decimal(s:inner) = 1" />
|
||||
<xsl:otherwise>
|
||||
<svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl" test="xs:decimal(s:inner) = 1">
|
||||
<xsl:attribute name="id">content-2</xsl:attribute>
|
||||
<xsl:attribute name="location">
|
||||
<xsl:apply-templates select="." mode="schematron-select-full-path" />
|
||||
</xsl:attribute>
|
||||
<svrl:text>The decimal value of s:inner should be 1.</svrl:text>
|
||||
</svrl:failed-assert>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
|
||||
<xsl:apply-templates select="*|comment()|processing-instruction()" mode="M3" />
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="text()" priority="-1" mode="M3" />
|
||||
<xsl:template match="@*|node()" priority="-2" mode="M3">
|
||||
<xsl:apply-templates select="*|comment()|processing-instruction()" mode="M3" />
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2017-2022 Koordinierungsstelle für IT-Standards (KoSIT)
|
||||
~
|
||||
~ Licensed 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:tns="http://validator.kosit.de/test-sample" version="1.0" xml:lang="en"
|
||||
targetNamespace="http://validator.kosit.de/test-sample" elementFormDefault="qualified">
|
||||
|
||||
<xs:element name="simple" type="tns:SimpleType" />
|
||||
<xs:element name="foo" type="tns:SimpleType" />
|
||||
|
||||
<xs:complexType name="SimpleType">
|
||||
<xs:sequence>
|
||||
<xs:element name="inner" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="content" type="xs:anyType" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<scenarios xmlns="http://www.xoev.de/de/validator/framework/1/scenarios" frameworkVersion="1.1.2">
|
||||
<name>XSLT-Runtime-Error-TestSuite</name>
|
||||
<author>QA</author>
|
||||
<date>2026-03-02</date>
|
||||
<description>
|
||||
<p>Szenario für Tests</p>
|
||||
</description>
|
||||
|
||||
<scenario>
|
||||
<name>Simple</name>
|
||||
<description>
|
||||
<p>Teste Fehlerfall.</p>
|
||||
</description>
|
||||
<namespace prefix="cri">http://www.xoev.de/de/validator/framework/1/createreportinput</namespace>
|
||||
<namespace prefix="test">http://validator.kosit.de/test-sample</namespace>
|
||||
<namespace prefix="rpt">http://validator.kosit.de/test-report</namespace>
|
||||
<match>/</match>
|
||||
|
||||
<validateWithXmlSchema>
|
||||
<resource>
|
||||
<name>Sample Schema</name>
|
||||
<location>repository/simple.xsd</location>
|
||||
</resource>
|
||||
</validateWithXmlSchema>
|
||||
<validateWithSchematron>
|
||||
<resource>
|
||||
<name>Sample Schematron</name>
|
||||
<location>repository/simple-xslt-runtime-error.xsl</location>
|
||||
</resource>
|
||||
</validateWithSchematron>
|
||||
<createReport>
|
||||
<resource>
|
||||
<name>Report für eRechnung</name>
|
||||
<location>repository/report.xsl</location>
|
||||
</resource>
|
||||
</createReport>
|
||||
</scenario>
|
||||
|
||||
<noScenarioReport>
|
||||
<resource>
|
||||
<name>default</name>
|
||||
<location>repository/report.xsl</location>
|
||||
</resource>
|
||||
</noScenarioReport>
|
||||
</scenarios>
|
||||
<!--
|
||||
~ Copyright 2017-2026 Koordinierungsstelle für IT-Standards (KoSIT)
|
||||
~
|
||||
~ Licensed 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.
|
||||
-->
|
||||
Loading…
Add table
Add a link
Reference in a new issue