import type { TransformEngineId } from '../transform/transformTypes'; import { parseXmlDocument } from './xmlValidation'; import type { DiagnosticMessage } from './validationTypes'; const XSLT_NAMESPACE = 'http://www.w3.org/1999/XSL/Transform'; export function validateXslt( text: string, engine: TransformEngineId = 'native-xsltprocessor' ): DiagnosticMessage[] { const { document: stylesheet, diagnostics } = parseXmlDocument( text, 'XSLT stylesheet' ); if (diagnostics.some((diagnostic) => diagnostic.severity === 'error')) { return diagnostics; } const root = stylesheet.documentElement; if (!root) { return [ ...diagnostics, { severity: 'error', source: 'XSLT stylesheet', message: 'The stylesheet has no document element.', }, ]; } if ( root.namespaceURI !== XSLT_NAMESPACE || !['stylesheet', 'transform'].includes(root.localName) ) { diagnostics.push({ severity: 'error', source: 'XSLT stylesheet', message: 'The root element should be xsl:stylesheet or xsl:transform in the XSLT namespace.', }); } const version = root.getAttribute('version'); if (!version) { diagnostics.push({ severity: 'warning', source: 'XSLT stylesheet', message: 'The stylesheet root should declare a version attribute.', }); } if (engine === 'native-xsltprocessor' && version && version !== '1.0') { diagnostics.push({ severity: 'warning', source: 'XSLT stylesheet', message: 'The native browser engine usually supports XSLT 1.0 only. XSLT 2.0/3.0 features may fail.', }); } return diagnostics; }