Module: Ksef::FA3::Validator
- Defined in:
- lib/ksef/fa3/validator.rb
Overview
XSD validation against the bundled FA(3) schema (DESIGN.md §7.7 tier 2).
The schema cannot be compiled as it ships. Its single xsd:import points at an
absolute http://crd.gov.pl/… URL, so libxml2 would try to fetch it over the network
at validation time — unacceptable for an offline, deterministic test suite, and a
silent hang or failure in an air-gapped deployment.
So the import is redirected to the bundled copy in memory. The pinned file on disk stays byte-for-byte identical, which is what keeps its recorded digest verifying (docs/REFERENCE.md §1).
Constant Summary collapse
- SCHEMA_DIR =
File.("schema", __dir__)
- MAIN_SCHEMA =
File.join(SCHEMA_DIR, "schemat_FA(3)_v1-0E.xsd")
- BASE_SCHEMA_DIR =
File.join(SCHEMA_DIR, "bazowe")
Class Method Summary collapse
-
.errors_for(xml) ⇒ Array<String>
Well-formedness is checked first, and separately. Nokogiri parses in recovery mode by default, so a document with an unclosed root or trailing text after it comes back as a usable tree — and that recovered tree validates clean against the schema.
-
.schema ⇒ Nokogiri::XML::Schema
Compiled once and memoised: compiling the FA(3) schema is expensive, and a single client validating many invoices should pay for it once.
- .valid?(xml) ⇒ Boolean
- .validate!(xml) ⇒ Object
Class Method Details
.errors_for(xml) ⇒ Array<String>
Well-formedness is checked first, and separately. Nokogiri parses in recovery
mode by default, so a document with an unclosed root or trailing text after it comes
back as a usable tree — and that recovered tree validates clean against the schema.
Until 2026-08-24 this method never looked at document.errors, so valid? returned
true for XML that is not XML. KSeF's first admission rule is "a correct XML 1.0
document" (docs/REFERENCE.md §15.1), and it is the rule most likely to be violated by
a broken template or a truncated upload.
41 42 43 44 45 46 47 |
# File 'lib/ksef/fa3/validator.rb', line 41 def errors_for(xml) document = xml.is_a?(Nokogiri::XML::Document) ? xml : Nokogiri::XML(xml) malformed = document.errors.map { |error| "not well-formed XML: #{error..strip}" } return malformed unless malformed.empty? schema.validate(document).map(&:message) end |
.schema ⇒ Nokogiri::XML::Schema
Compiled once and memoised: compiling the FA(3) schema is expensive, and a single client validating many invoices should pay for it once.
27 28 29 |
# File 'lib/ksef/fa3/validator.rb', line 27 def schema @schema ||= Nokogiri::XML::Schema.from_document(rewritten_schema_document) end |
.valid?(xml) ⇒ Boolean
50 |
# File 'lib/ksef/fa3/validator.rb', line 50 def valid?(xml) = errors_for(xml).empty? |
.validate!(xml) ⇒ Object
53 54 55 56 57 58 59 |
# File 'lib/ksef/fa3/validator.rb', line 53 def validate!(xml) errors = errors_for(xml) return true if errors.empty? detail = errors.map { |e| " - #{e}" }.join("\n") raise ValidationError, "Invoice does not conform to the FA(3) schema:\n#{detail}" end |