feat(core): improve in-memory validation, FatturaPA detection coverage, and published type compatibility

This commit is contained in:
2026-04-16 20:30:56 +00:00
parent 55bee02a2e
commit 3f37f6538c
60 changed files with 5723 additions and 6678 deletions
+17 -12
View File
@@ -4,29 +4,33 @@ import type { ValidationResult } from '../../interfaces/common.js';
import { UBLDocumentType } from './ubl.types.js';
import { DOMParser, xpath } from '../../plugins.js';
const ublValidatorParser = new DOMParser();
const ublValidatorNamespaces = {
cbc: 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
cac: 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
};
const ublValidatorSelect = xpath.useNamespaces(ublValidatorNamespaces);
/**
* Base validator for UBL-based invoice formats
*/
export abstract class UBLBaseValidator extends BaseValidator {
protected doc: Document;
protected namespaces: Record<string, string>;
protected select: xpath.XPathSelect;
protected doc!: Document;
protected namespaces!: Record<string, string>;
protected select!: xpath.XPathSelect;
constructor(xml: string) {
constructor(xml: string, doc?: Document) {
super(xml);
try {
// Parse XML document
this.doc = new DOMParser().parseFromString(xml, 'application/xml');
// Reuse an existing parsed document when available.
this.doc = doc ?? ublValidatorParser.parseFromString(xml, 'application/xml');
// Set up namespaces for XPath queries
this.namespaces = {
cbc: 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
cac: 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'
};
this.namespaces = ublValidatorNamespaces;
// Create XPath selector with namespaces
this.select = xpath.useNamespaces(this.namespaces);
this.select = ublValidatorSelect;
} catch (error) {
this.addError('UBL-PARSE', `Failed to parse XML: ${error}`, '/');
}
@@ -101,7 +105,8 @@ export abstract class UBLBaseValidator extends BaseValidator {
* @returns Text value or empty string if not found
*/
protected getText(xpathExpr: string, context?: Node): string {
const node = this.select(xpathExpr, context || this.doc)[0];
const result = this.select(xpathExpr, context || this.doc);
const node = Array.isArray(result) ? result[0] : null;
return node ? (node.textContent || '') : '';
}