Inconsistent Error Handling: XSLT-Based Resource Fails, While Pure Resource Completes Validation
Closed this issue · 6 comments
Dear Repository Maintainer,
We are encountering an issue where there is a discrepancy between Pure and XSLT validations using the same Schematron file in version 7.1.2 of your library.
Description:
During our validation process, Pure validation logs an error message to the console but continues and completes the validation. In contrast, XSLT validation, using the same Schematron file, throws the same error and halts the validation process.
Error Messages and Files:
- Error messages: See attached file validation_errors.txt.
- XML example, Schematron, and XSLT files: Available in the attached pure-vs-xslt.zip.
Issue:
For some reason, the Pure validation catches the error but does not re-throw it, whereas the XSLT validation re-throws the error, causing it to stop. This difference in behavior is causing inconsistencies in our validation workflow.
Could you please investigate why the XSLT validation behaves differently from the Pure validation in this scenario? Any insights or suggestions for achieving consistent behavior would be greatly appreciated.
Thank you for your assistance and for providing such a valuable tool.
Best regards,
Gediminas
@phax perhaps you had some time to look at this?
@gediminasre thanks for the reminder. Indeed there is an explanation for this.
a) Pure and XSLT behave totally different because they support a different condition language (XPath vs. XPath + XSLT) and the execution logic is different (Java vs. XSLT element iteration)
b) See e.g. #169 for another very similar case on why they behave differently
However, I acknowledge the inconsistency, that the error is not re-thrown and I will look into it
Thanks for coming back @phax
To clarify, XSLT should ideally follow the Pure validation pattern and not throw the error, allowing the full validation process to complete.
@gediminasre does an SVRL like this suit your needs:
<?xml version="1.0" encoding="UTF-8"?>
<svrl:schematron-output xmlns:svrl="http://purl.oclc.org/dsdl/svrl" title="eForms-DE Schematron Version @eforms-de-schematron.version.full@ compliant with eForms-DE specification @eforms-de.version.full@" phase="doe-validation-phase">
<svrl:ns-prefix-in-attribute-values prefix="can" uri="urn:oasis:names:specification:ubl:schema:xsd:ContractAwardNotice-2" />
<svrl:ns-prefix-in-attribute-values prefix="cn" uri="urn:oasis:names:specification:ubl:schema:xsd:ContractNotice-2" />
<svrl:ns-prefix-in-attribute-values prefix="pin" uri="urn:oasis:names:specification:ubl:schema:xsd:PriorInformationNotice-2" />
<svrl:ns-prefix-in-attribute-values prefix="brin" uri="http://data.europa.eu/p27/eforms-business-registration-information-notice/1" />
<svrl:ns-prefix-in-attribute-values prefix="cbc" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" />
<svrl:ns-prefix-in-attribute-values prefix="cac" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" />
<svrl:ns-prefix-in-attribute-values prefix="ext" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" />
<svrl:ns-prefix-in-attribute-values prefix="efac" uri="http://data.europa.eu/p27/eforms-ubl-extension-aggregate-components/1" />
<svrl:ns-prefix-in-attribute-values prefix="efext" uri="http://data.europa.eu/p27/eforms-ubl-extensions/1" />
<svrl:ns-prefix-in-attribute-values prefix="efbc" uri="http://data.europa.eu/p27/eforms-ubl-extension-basic-components/1" />
<svrl:ns-prefix-in-attribute-values prefix="xs" uri="http://www.w3.org/2001/XMLSchema" />
<svrl:active-pattern id="global-variable-pattern" />
<svrl:active-pattern id="technical-sanity-pattern" />
<svrl:fired-rule context="//$ROOT-NODE/cbc:CustomizationID" />
<svrl:failed-assert id="SR-DE-1" location="/can:ContractAwardNotice/cbc:CustomizationID" test="text() = $EFORMS-DE-ID" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'text() = $EFORMS-DE-ID'
Error: The string "eforms-de-1.1" cannot be cast to a boolean</svrl:text>
</svrl:failed-assert>
<svrl:active-pattern id="cardinality-pattern" />
<svrl:fired-rule context="//$ROOT-NODE" />
<svrl:failed-assert id="CR-DE-BT-105" location="/can:ContractAwardNotice" test="if ($SUBTYPE = $SUBTYPES-BT-105) then exists(cac:TenderingProcess/cbc:ProcedureCode) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-105) then exists(cac:TenderingProcess/cbc:ProcedureCode) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:fired-rule context="//$ROOT-NODE/cbc:RequestedPublicationDate" />
<svrl:fired-rule context="//$ROOT-NODE/cac:ProcurementProject" />
<svrl:failed-assert id="CR-DE-BT-21" location="/can:ContractAwardNotice/cac:ProcurementProject" test="boolean(normalize-space((cbc:Name[./@languageID = $MAIN-LANG])))" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'boolean(normalize-space((cbc:Name[./@languageID = $MAIN-LANG])))'
Error: The string "DEU" cannot be cast to a boolean</svrl:text>
</svrl:failed-assert>
<svrl:fired-rule context="//$ROOT-NODE/cac:ProcurementProject/cac:RealizedLocation" />
<svrl:fired-rule context="//$ROOT-NODE/cac:ProcurementProjectLot[cbc:ID/@schemeName = 'Lot']/cac:ProcurementProject" />
<svrl:failed-assert id="CR-DE-BT-21-Lot" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:ProcurementProject" test="boolean(normalize-space((cbc:Name[./@languageID = $MAIN-LANG])))" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'boolean(normalize-space((cbc:Name[./@languageID = $MAIN-LANG])))'
Error: The string "DEU" cannot be cast to a boolean</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="BR-DE-21-A" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:ProcurementProject" test="if ($SUBTYPE = $SUBTYPES-BT-06) then (count(cac:ProcurementAdditionalType/cbc:ProcurementTypeCode[@listName = 'strategic-procurement']) ge 1) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-06) then (count(cac:ProcurementAdditionalType/cbc:ProcurementTypeCode[@listName = 'strategic-procurement']) ge 1) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="BR-DE-21-B" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:ProcurementProject" test="if ($SUBTYPE = $SUBTYPES-BT-06) then (count(cac:ProcurementAdditionalType/cbc:ProcurementTypeCode[@listName = 'strategic-procurement']) le 3) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-06) then (count(cac:ProcurementAdditionalType/cbc:ProcurementTypeCode[@listName = 'strategic-procurement']) le 3) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="BR-DE-22" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:ProcurementProject" test="if ($SUBTYPE = $SUBTYPES-BT-06) then (count(cac:ProcurementAdditionalType/cbc:ProcurementTypeCode[@listName = 'strategic-procurement']) = count(distinct-values(cac:ProcurementAdditionalType/cbc:ProcurementTypeCode[@listName = 'strategic-procurement']))) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-06) then (count(cac:ProcurementAdditionalType/cbc:ProcurementTypeCode[@listName = 'strategic-procurement']) = count(distinct-values(cac:ProcurementAdditionalType/cbc:ProcurementTypeCode[@listName = 'strategic-procurement']))) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:fired-rule context="//$ROOT-NODE/cac:ProcurementProjectLot[cbc:ID/@schemeName = 'Lot' or cbc:ID/@schemeName = 'Part']/cac:ProcurementProject/cac:RealizedLocation/cac:Address" />
<svrl:fired-rule context="//$ROOT-NODE/cac:ProcurementProjectLot[cbc:ID/@schemeName = 'Lot']/cac:TenderingTerms" />
<svrl:failed-assert id="CR-DE-BT-771-Lot" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:TenderingTerms" test="if ($SUBTYPE = $SUBTYPES-BT-771-772) then (count(cac:TendererQualificationRequest[not(cbc:CompanyLegalFormCode)]/cac:SpecificTendererRequirement[(cbc:TendererRequirementTypeCode[@listName = 'missing-info-submission'])]) = 1) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-771-772) then (count(cac:TendererQualificationRequest[not(cbc:CompanyLegalFormCode)]/cac:SpecificTendererRequirement[(cbc:TendererRequirementTypeCode[@listName = 'missing-info-submission'])]) = 1) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="CR-DE-BT-772-Lot" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:TenderingTerms" test="if ($SUBTYPE = $SUBTYPES-BT-771-772) then (count(cac:TendererQualificationRequest[not(cbc:CompanyLegalFormCode)]/cac:SpecificTendererRequirement[(cbc:TendererRequirementTypeCode[@listName = 'missing-info-submission'])]/cbc:Description[./@languageID = $MAIN-LANG]) = 1) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-771-772) then (count(cac:TendererQualificationRequest[not(cbc:CompanyLegalFormCode)]/cac:SpecificTendererRequirement[(cbc:TendererRequirementTypeCode[@listName = 'missing-info-submission'])]/cbc:Description[./@languageID = $MAIN-LANG]) = 1) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="SR-DE-21" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:TenderingTerms" test="if ($SUBTYPE = $SUBTYPES-BT-771-772) then (count(cac:TendererQualificationRequest) >= 1) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-771-772) then (count(cac:TendererQualificationRequest) >= 1) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="CR-DE-BT-97-Lot" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:TenderingTerms" test="if ($SUBTYPE = $SUBTYPES-BT-97) then exists(cac:Language/cbc:ID) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-97) then exists(cac:Language/cbc:ID) else true()'
Error: Cannot compare xs:boolean to xs:string</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="SR-DE-23" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:TenderingTerms" test="if ($SUBTYPE = $SUBTYPES-BT-15) then (count(cac:CallForTendersDocumentReference) >= 1) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-15) then (count(cac:CallForTendersDocumentReference) >= 1) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:fired-rule context="//$ROOT-NODE/cac:ProcurementProjectLot[cbc:ID/@schemeName = 'Lot']" />
<svrl:failed-assert id="CR-DE-BT-63-Lot" location="/can:ContractAwardNotice/cac:ProcurementProjectLot" test="if ($SUBTYPE = $SUBTYPES-BT-63) then boolean(normalize-space(cac:TenderingTerms/cbc:VariantConstraintCode)) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-63) then boolean(normalize-space(cac:TenderingTerms/cbc:VariantConstraintCode)) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="CR-DE-BT-17-Lot" location="/can:ContractAwardNotice/cac:ProcurementProjectLot" test="if ($SUBTYPE = $SUBTYPES-BT-17) then boolean(normalize-space(cac:TenderingProcess/cbc:SubmissionMethodCode[@listName = 'esubmission'])) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-17) then boolean(normalize-space(cac:TenderingProcess/cbc:SubmissionMethodCode[@listName = 'esubmission'])) else true()'
Error: Cannot compare xs:boolean to xs:string</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="CR-DE-BT-717-Lot" location="/can:ContractAwardNotice/cac:ProcurementProjectLot" test="if ($SUBTYPE = $SUBTYPES-BT-717) then exists(cac:TenderingTerms/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/efext:EformsExtension/efac:StrategicProcurement/efbc:ApplicableLegalBasis[@listName = 'cvd-scope']) else true()">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-717) then exists(cac:TenderingTerms/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/efext:EformsExtension/efac:StrategicProcurement/efbc:ApplicableLegalBasis[@listName = 'cvd-scope']) else true()'
Error: Cannot compare xs:boolean to xs:double</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert id="CR-DE-BT-769-Lot" location="/can:ContractAwardNotice/cac:ProcurementProjectLot" test="if ($SUBTYPE = $SUBTYPES-BT-769) then boolean(normalize-space(cac:TenderingTerms/cbc:MultipleTendersCode)) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if ($SUBTYPE = $SUBTYPES-BT-769) then boolean(normalize-space(cac:TenderingTerms/cbc:MultipleTendersCode)) else true()'
Error: Cannot compare xs:boolean to xs:string</svrl:text>
</svrl:failed-assert>
<svrl:active-pattern id="codelists" />
<svrl:fired-rule context="//$ROOT-NODE/cac:ContractingParty/cac:ContractingPartyType/cbc:PartyTypeCode[@listName = 'buyer-legal-type']" />
<svrl:fired-rule context="//$ROOT-NODE/cac:TenderingProcess/cbc:ProcedureCode" />
<svrl:fired-rule context="//$ROOT-NODE/cac:TenderingTerms/cac:ProcurementLegislationDocumentReference/cbc:ID" />
<svrl:active-pattern id="conditional-mandatory" />
<svrl:fired-rule context="//$ROOT-NODE/cac:ProcurementProjectLot[cbc:ID/@schemeName = 'Lot']/cac:ProcurementProject/cac:ProcurementAdditionalType" />
<svrl:fired-rule context="//$ROOT-NODE/cac:ProcurementProjectLot[cbc:ID/@schemeName = ('Part', 'Lot', 'LotsGroup')]/cac:ProcurementProject/cbc:Note" />
<svrl:fired-rule context="//$ROOT-NODE/cac:ProcurementProjectLot[cbc:ID/@schemeName = ('Lot', 'Part')]/cac:TenderingTerms/cac:AwardingTerms/cac:AwardingCriterion/cac:SubordinateAwardingCriterion" />
<svrl:failed-assert id="BR-DE-23" location="/can:ContractAwardNotice/cac:ProcurementProjectLot/cac:TenderingTerms/cac:AwardingTerms/cac:AwardingCriterion/cac:SubordinateAwardingCriterion" test="if (normalize-space($AwardCriterionParameter/efbc:ParameterCode/text()) = 'per-exa' and number(normalize-space($AwardCriterionParameter/efbc:ParameterNumeric/text())) ge 10 ) then (boolean(normalize-space(cbc:AwardingCriterionTypeCode)) and boolean(normalize-space(cbc:Name[./@languageID = $MAIN-LANG])) ) else true()" role="error">
<svrl:text>Failed to evaluate XPath expression to a boolean.
Test: 'if (normalize-space($AwardCriterionParameter/efbc:ParameterCode/text()) = 'per-exa' and number(normalize-space($AwardCriterionParameter/efbc:ParameterNumeric/text())) ge 10 ) then (boolean(normalize-space(cbc:AwardingCriterionTypeCode)) and boolean(normalize-space(cbc:Name[./@languageID = $MAIN-LANG])) ) else true()'
Error: A sequence of more than one item is not allowed as the first argument of fn:normalize-space() ("0.4", "0.6") </svrl:text>
</svrl:failed-assert>
<svrl:active-pattern id="doe-validation-pattern" />
<svrl:fired-rule context="//$ROOT-NODE" />
<svrl:failed-assert location="/can:ContractAwardNotice" test="$BT-05-DATE ge $CURRENT-DATE - xs:dayTimeDuration('P1D')">
<svrl:text>Date of BT-05= must be less than 1 day in the past. Current date=2024-07-12+02:00. Difference=</svrl:text>
</svrl:failed-assert>
<svrl:failed-assert location="/can:ContractAwardNotice" test="$BT-05-DATE le $CURRENT-DATE + xs:dayTimeDuration('P1D')">
<svrl:text>Date of BT-05= must be less than 1 day in the future. Current date=2024-07-12+02:00. Difference=$CURRENT-DATE + xs:dayTimeDuration('P1D')</svrl:text>
</svrl:failed-assert>
</svrl:schematron-output>
@phax this SVRL report looks just what we need. Thank you very much!
Great :) Will be part of the next 8.x release