typesxml
Version:
Open source XML library written in TypeScript
734 lines • 34 kB
JavaScript
"use strict";
/*******************************************************************************
* Copyright (c) 2023-2026 Maxprograms.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-v10.html
*
* Contributors:
* Maxprograms - initial API and implementation
*******************************************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const DOMBuilder_js_1 = require("../DOMBuilder.js");
const SAXParser_js_1 = require("../SAXParser.js");
const SchemaBuilder_js_1 = require("../schema/SchemaBuilder.js");
const XSDSemanticValidator_js_1 = require("../schema/XSDSemanticValidator.js");
const RootAttributeHandler_js_1 = require("./RootAttributeHandler.js");
const SUITE_FILE = './tests/xmlschema2006-11-06/suite.xml';
// Path to the Boeing testSet file relative to the suite root
const BOEING_TESTSET = 'boeingMeta/BoeingXSDTestSet.testSet';
// Path to the NIST testSet file relative to the suite root
const NIST_TESTSET = 'nistMeta/NISTXMLSchemaDatatypes.testSet';
// Directory containing the Microsoft testSet files (all named *_w3c.xml)
const MS_META_DIR = 'msMeta';
// Directory containing the SUN testSet files (13 .testSet files)
const SUN_META_DIR = 'sunMeta';
class XMLSchemaTestSuite {
grandTotal = 0;
grandPassed = 0;
grandFailed = 0;
grandSkipped = 0;
setResults = [];
constructor() {
if (!(0, node_fs_1.existsSync)(SUITE_FILE)) {
throw new Error('XML Schema Test Suite not found at ' + SUITE_FILE);
}
}
run() {
const suiteDir = (0, node_path_1.dirname)((0, node_path_1.resolve)(SUITE_FILE));
// Boeing: one dedicated testSet file
const boeingPath = (0, node_path_1.resolve)(suiteDir, BOEING_TESTSET);
if ((0, node_fs_1.existsSync)(boeingPath)) {
const stats = this.runBoeingTestSet(boeingPath);
this.setResults.push(stats);
this.grandTotal += stats.total;
this.grandPassed += stats.passed;
this.grandFailed += stats.failed;
this.grandSkipped += stats.skipped;
}
else {
console.warn('Boeing test set not found: ' + boeingPath);
}
// NIST: one dedicated testSet file
const nistPath = (0, node_path_1.resolve)(suiteDir, NIST_TESTSET);
if ((0, node_fs_1.existsSync)(nistPath)) {
const stats = this.runNistTestSet(nistPath);
this.setResults.push(stats);
this.grandTotal += stats.total;
this.grandPassed += stats.passed;
this.grandFailed += stats.failed;
this.grandSkipped += stats.skipped;
}
else {
console.warn('NIST test set not found: ' + nistPath);
}
// Microsoft: 17 testSet files in msMeta/, all named *_w3c.xml
const msMetaDir = (0, node_path_1.resolve)(suiteDir, MS_META_DIR);
if ((0, node_fs_1.existsSync)(msMetaDir)) {
const msStats = { contributor: 'Microsoft', name: 'MS-XSD-2006', total: 0, passed: 0, failed: 0, skipped: 0 };
const msFiles = (0, node_fs_1.readdirSync)(msMetaDir)
.filter((f) => f.endsWith('_w3c.xml'))
.sort();
for (const msFile of msFiles) {
const msPath = (0, node_path_1.resolve)(msMetaDir, msFile);
this.runMicrosoftTestSet(msPath, msStats);
}
this.setResults.push(msStats);
this.grandTotal += msStats.total;
this.grandPassed += msStats.passed;
this.grandFailed += msStats.failed;
this.grandSkipped += msStats.skipped;
}
else {
console.warn('Microsoft meta directory not found: ' + msMetaDir);
}
// SUN: 13 testSet files in sunMeta/
const sunMetaDir = (0, node_path_1.resolve)(suiteDir, SUN_META_DIR);
if ((0, node_fs_1.existsSync)(sunMetaDir)) {
const sunStats = { contributor: 'SUN', name: 'SUN-XSD-2006', total: 0, passed: 0, failed: 0, skipped: 0 };
const sunFiles = (0, node_fs_1.readdirSync)(sunMetaDir)
.filter((f) => f.endsWith('.testSet'))
.sort();
for (const sunFile of sunFiles) {
const sunPath = (0, node_path_1.resolve)(sunMetaDir, sunFile);
this.runSunTestSet(sunPath, sunStats);
}
this.setResults.push(sunStats);
this.grandTotal += sunStats.total;
this.grandPassed += sunStats.passed;
this.grandFailed += sunStats.failed;
this.grandSkipped += sunStats.skipped;
}
else {
console.warn('SUN meta directory not found: ' + sunMetaDir);
}
this.printReport();
}
// -------------------------------------------------------------------------
// Microsoft harness
//
// Structure: msMeta/*_w3c.xml (17 files)
// msData/... (referenced as ../msData/ from testSet files)
//
// Rules:
// schemaTest – exactly one <schemaDocument> per group. Parsed normally;
// XSDSemanticValidator checks structural validity.
//
// instanceTest – each instance carries xsi:schemaLocation. SAXParser with
// setValidating(true) resolves the grammar automatically.
// Some groups have instanceTest with no schemaTest — those
// instances validate against schemas they declare themselves
// via xsi:schemaLocation.
//
// Stats are accumulated into a single SetStats passed by reference so that
// all 17 files contribute to one Microsoft total in the report.
// -------------------------------------------------------------------------
runMicrosoftTestSet(testSetPath, stats) {
const testSetDir = (0, node_path_1.dirname)(testSetPath);
const doc = this.parseXML(testSetPath);
if (!doc) {
console.warn('Microsoft: could not parse ' + testSetPath);
return;
}
const root = doc.getRoot();
if (!root) {
return;
}
for (const testGroupEl of root.getChildren()) {
if (this.localName(testGroupEl.getName()) !== 'testGroup') {
continue;
}
const groupName = testGroupEl.getAttribute('name')?.getValue() || '';
let groupSchemaGrammar;
for (const child of testGroupEl.getChildren()) {
const childLocalName = this.localName(child.getName());
// ---- schemaTest ----
if (childLocalName === 'schemaTest') {
const schemaDocEl = this.findChildByLocalName(child, 'schemaDocument');
if (!schemaDocEl) {
continue;
}
const href = this.getXlinkHref(schemaDocEl);
if (!href) {
continue;
}
const schemaPath = (0, node_path_1.resolve)(testSetDir, href);
if (!(0, node_fs_1.existsSync)(schemaPath)) {
continue;
}
const expectedEl = this.findChildByLocalName(child, 'expected');
const expected = expectedEl?.getAttribute('validity')?.getValue() || 'valid';
const testName = child.getAttribute('name')?.getValue() || groupName;
let actual;
try {
const parser = new SAXParser_js_1.SAXParser();
const handler = new DOMBuilder_js_1.DOMBuilder();
parser.setContentHandler(handler);
parser.parseFile(schemaPath);
const schemaRoot = handler.getDocument()?.getRoot();
if (schemaRoot) {
XSDSemanticValidator_js_1.XSDSemanticValidator.validate(schemaRoot);
}
const builder = new SchemaBuilder_js_1.SchemaBuilder();
const built = builder.buildGrammar(schemaPath);
groupSchemaGrammar = this.isAccepted(child) ? built : undefined;
actual = 'valid';
}
catch (_e) {
groupSchemaGrammar = undefined;
actual = 'invalid';
}
stats.total++;
if (actual === expected) {
stats.passed++;
}
else if (!this.isAccepted(child)) {
stats.skipped++;
}
else {
stats.failed++;
console.log(' -- ' + testName + ': expected=' + expected + ' actual=' + actual + ' [' + schemaPath + ']');
}
continue;
}
// ---- instanceTest ----
if (childLocalName !== 'instanceTest') {
continue;
}
const instanceDocEl = this.findChildByLocalName(child, 'instanceDocument');
if (!instanceDocEl) {
continue;
}
const href = this.getXlinkHref(instanceDocEl);
if (!href) {
continue;
}
const instancePath = (0, node_path_1.resolve)(testSetDir, href);
if (!(0, node_fs_1.existsSync)(instancePath)) {
continue;
}
const expectedEl = this.findChildByLocalName(child, 'expected');
const expected = expectedEl?.getAttribute('validity')?.getValue() || 'valid';
const testName = child.getAttribute('name')?.getValue() || groupName;
let actual;
try {
const checkParser = new SAXParser_js_1.SAXParser();
const checkHandler = new RootAttributeHandler_js_1.RootAttributeHandler();
checkParser.setContentHandler(checkHandler);
const savedWarn = console.warn;
console.warn = () => { };
try {
checkParser.parseFile(instancePath);
}
catch (_ignored) { }
console.warn = savedWarn;
const needsInjection = groupSchemaGrammar !== undefined
&& !checkHandler.hasSchemaRef();
const parser = new SAXParser_js_1.SAXParser();
const handler = new DOMBuilder_js_1.DOMBuilder();
parser.setContentHandler(handler);
if (needsInjection) {
handler.setGrammar(groupSchemaGrammar);
}
parser.setValidating(true);
parser.parseFile(instancePath);
actual = 'valid';
}
catch (_e) {
actual = 'invalid';
}
stats.total++;
if (actual === expected) {
stats.passed++;
}
else if (!this.isAccepted(child)) {
stats.skipped++;
}
else {
stats.failed++;
console.log(' -- ' + testName + ': expected=' + expected + ' actual=' + actual + ' [' + instancePath + ']');
}
}
}
}
// -------------------------------------------------------------------------
// SUN harness
//
// Structure: sunMeta/*.testSet (13 files)
// sunData/combined/NNN/ — instance tests without xsi:schemaLocation
// sunData/TOPIC/... — instance tests with xsi:schemaLocation
//
// Rules (per AnnotatedTSSchema.xsd section 5.2):
// Validation must start with no stipulated declaration or definition.
// The processor must find the schema on its own (via xsi:schemaLocation,
// xsi:noNamespaceSchemaLocation, or namespace resolution).
// No grammar injection is permitted for any SUN instance test.
//
// schemaTest – one <schemaDocument> per group. Parsed normally;
// XSDSemanticValidator checks structural validity.
//
// instanceTest – setValidating(true); the parser resolves schemas
// autonomously. combined/ instances have no
// xsi:schemaLocation (processor starts with no schema).
//
// Stats are accumulated into a single SetStats passed by reference.
// -------------------------------------------------------------------------
runSunTestSet(testSetPath, stats) {
const testSetDir = (0, node_path_1.dirname)(testSetPath);
const doc = this.parseXML(testSetPath);
if (!doc) {
console.warn('SUN: could not parse ' + testSetPath);
return;
}
const root = doc.getRoot();
if (!root) {
return;
}
for (const testGroupEl of root.getChildren()) {
if (this.localName(testGroupEl.getName()) !== 'testGroup') {
continue;
}
const groupName = testGroupEl.getAttribute('name')?.getValue() || '';
// Build the group's SchemaGrammar from the schemaTest first, so it
// can be injected into each instanceTest in the same group.
let groupSchemaGrammar;
const groupChildren = testGroupEl.getChildren();
for (const child of groupChildren) {
const childLocalName = this.localName(child.getName());
// ---- schemaTest ----
if (childLocalName === 'schemaTest') {
const schemaDocEl = this.findChildByLocalName(child, 'schemaDocument');
if (!schemaDocEl) {
continue;
}
const href = this.getXlinkHref(schemaDocEl);
if (!href) {
continue;
}
const schemaPath = (0, node_path_1.resolve)(testSetDir, href);
if (!(0, node_fs_1.existsSync)(schemaPath)) {
continue;
}
const expectedEl = this.findChildByLocalName(child, 'expected');
const expected = expectedEl?.getAttribute('validity')?.getValue() || 'valid';
const testName = child.getAttribute('name')?.getValue() || groupName;
let actual;
try {
const parser = new SAXParser_js_1.SAXParser();
const handler = new DOMBuilder_js_1.DOMBuilder();
parser.setContentHandler(handler);
parser.parseFile(schemaPath);
const schemaRoot = handler.getDocument()?.getRoot();
if (schemaRoot) {
XSDSemanticValidator_js_1.XSDSemanticValidator.validate(schemaRoot);
}
const builder = new SchemaBuilder_js_1.SchemaBuilder();
groupSchemaGrammar = builder.buildGrammar(schemaPath);
actual = 'valid';
}
catch (_e) {
groupSchemaGrammar = undefined;
actual = 'invalid';
}
stats.total++;
if (actual === expected) {
stats.passed++;
}
else if (!this.isAccepted(child)) {
stats.skipped++;
}
else {
stats.failed++;
console.log(' -- ' + testName + ': expected=' + expected + ' actual=' + actual + ' [' + schemaPath + ']');
}
continue;
}
// ---- instanceTest ----
// Per the TS spec (AnnotatedTSSchema.xsd), the testGroup groups
// the schema with its instance documents. The schemaTest grammar
// is injected into the handler so xsi:type values defined in that
// schema are reachable during validation.
if (childLocalName !== 'instanceTest') {
continue;
}
const instanceDocEl = this.findChildByLocalName(child, 'instanceDocument');
if (!instanceDocEl) {
continue;
}
const href = this.getXlinkHref(instanceDocEl);
if (!href) {
continue;
}
const instancePath = (0, node_path_1.resolve)(testSetDir, href);
if (!(0, node_fs_1.existsSync)(instancePath)) {
continue;
}
const expectedEl = this.findChildByLocalName(child, 'expected');
const expected = expectedEl?.getAttribute('validity')?.getValue() || 'valid';
const testName = child.getAttribute('name')?.getValue() || groupName;
let actual;
try {
const parser = new SAXParser_js_1.SAXParser();
const handler = new DOMBuilder_js_1.DOMBuilder();
parser.setContentHandler(handler);
if (groupSchemaGrammar) {
handler.setGrammar(groupSchemaGrammar);
}
parser.setValidating(true);
parser.parseFile(instancePath);
actual = 'valid';
}
catch (_e) {
actual = 'invalid';
}
stats.total++;
if (actual === expected) {
stats.passed++;
}
else if (!this.isAccepted(child)) {
stats.skipped++;
}
else {
stats.failed++;
console.log(' -- ' + testName + ': expected=' + expected + ' actual=' + actual + ' [' + instancePath + ']');
}
}
}
}
// -------------------------------------------------------------------------
// NIST harness
//
// Structure: nistMeta/NISTXMLSchemaDatatypes.testSet
// nistData/atomic|list|union/TYPE/Schema+Instance/
//
// Rules:
// schemaTest – exactly one <schemaDocument> per group. Parsed normally;
// XSDSemanticValidator checks structural validity.
//
// instanceTest – each instance carries xsi:schemaLocation pointing to the
// .xsd in the same Schema+Instance/ directory. SAXParser
// with setValidating(true) resolves it automatically.
// -------------------------------------------------------------------------
runNistTestSet(testSetPath) {
const testSetDir = (0, node_path_1.dirname)(testSetPath);
const stats = { contributor: 'NIST', name: 'NIST2004-01-14', total: 0, passed: 0, failed: 0, skipped: 0 };
const doc = this.parseXML(testSetPath);
if (!doc) {
console.warn('NIST: could not parse ' + testSetPath);
return stats;
}
const root = doc.getRoot();
if (!root) {
return stats;
}
for (const testGroupEl of root.getChildren()) {
if (this.localName(testGroupEl.getName()) !== 'testGroup') {
continue;
}
const groupName = testGroupEl.getAttribute('name')?.getValue() || '';
for (const child of testGroupEl.getChildren()) {
const childLocalName = this.localName(child.getName());
// ---- schemaTest ----
if (childLocalName === 'schemaTest') {
const schemaDocEl = this.findChildByLocalName(child, 'schemaDocument');
if (!schemaDocEl) {
continue;
}
const href = this.getXlinkHref(schemaDocEl);
if (!href) {
continue;
}
const schemaPath = (0, node_path_1.resolve)(testSetDir, href);
if (!(0, node_fs_1.existsSync)(schemaPath)) {
continue;
}
const expectedEl = this.findChildByLocalName(child, 'expected');
const expected = expectedEl?.getAttribute('validity')?.getValue() || 'valid';
const testName = child.getAttribute('name')?.getValue() || groupName;
let actual;
try {
const parser = new SAXParser_js_1.SAXParser();
const handler = new DOMBuilder_js_1.DOMBuilder();
parser.setContentHandler(handler);
parser.parseFile(schemaPath);
const schemaRoot = handler.getDocument()?.getRoot();
if (schemaRoot) {
XSDSemanticValidator_js_1.XSDSemanticValidator.validate(schemaRoot);
}
actual = 'valid';
}
catch (_e) {
actual = 'invalid';
}
stats.total++;
if (actual === expected) {
stats.passed++;
}
else if (!this.isAccepted(child)) {
stats.skipped++;
}
else {
stats.failed++;
console.log(' -- ' + testName + ': expected=' + expected + ' actual=' + actual + ' [' + schemaPath + ']');
}
continue;
}
// ---- instanceTest ----
// Instances carry xsi:schemaLocation — no grammar injection needed.
if (childLocalName !== 'instanceTest') {
continue;
}
const instanceDocEl = this.findChildByLocalName(child, 'instanceDocument');
if (!instanceDocEl) {
continue;
}
const href = this.getXlinkHref(instanceDocEl);
if (!href) {
continue;
}
const instancePath = (0, node_path_1.resolve)(testSetDir, href);
if (!(0, node_fs_1.existsSync)(instancePath)) {
continue;
}
const expectedEl = this.findChildByLocalName(child, 'expected');
const expected = expectedEl?.getAttribute('validity')?.getValue() || 'valid';
const testName = child.getAttribute('name')?.getValue() || groupName;
let actual;
try {
const parser = new SAXParser_js_1.SAXParser();
const handler = new DOMBuilder_js_1.DOMBuilder();
parser.setContentHandler(handler);
parser.setValidating(true);
parser.parseFile(instancePath);
actual = 'valid';
}
catch (_e) {
actual = 'invalid';
}
stats.total++;
if (actual === expected) {
stats.passed++;
}
else if (!this.isAccepted(child)) {
stats.skipped++;
}
else {
stats.failed++;
console.log(' -- ' + testName + ': expected=' + expected + ' actual=' + actual + ' [' + instancePath + ']');
}
}
}
return stats;
}
// -------------------------------------------------------------------------
// Boeing harness
//
// Structure: boeingMeta/BoeingXSDTestSet.testSet
// boeingData/ipoN/ (N = 1..6)
//
// Rules:
// schemaTest – one or more <schemaDocument> elements. Each is parsed
// independently; the XSD file's own xs:import/xs:include
// declarations are resolved automatically by the parser.
// XSDSemanticValidator checks the structural validity of
// each document. One failure fails the whole schemaTest.
//
// instanceTest – each instance carries xsi:schemaLocation with a relative
// path to the schema in the same directory. SAXParser with
// setValidating(true) resolves and loads it automatically.
// -------------------------------------------------------------------------
runBoeingTestSet(testSetPath) {
const testSetDir = (0, node_path_1.dirname)(testSetPath);
const stats = { contributor: 'Boeing', name: 'BoeingXSDTestCases', total: 0, passed: 0, failed: 0, skipped: 0 };
const doc = this.parseXML(testSetPath);
if (!doc) {
console.warn('Boeing: could not parse ' + testSetPath);
return stats;
}
const root = doc.getRoot();
if (!root) {
return stats;
}
for (const testGroupEl of root.getChildren()) {
if (this.localName(testGroupEl.getName()) !== 'testGroup') {
continue;
}
const groupName = testGroupEl.getAttribute('name')?.getValue() || '';
for (const child of testGroupEl.getChildren()) {
const childLocalName = this.localName(child.getName());
// ---- schemaTest ----
// Each listed schemaDocument is an independent XSD file.
// Each file carries its own xs:import/xs:include declarations
// that the parser resolves automatically. We simply parse every
// listed document and run XSDSemanticValidator on its root.
// One failure in any document fails the whole schemaTest.
if (childLocalName === 'schemaTest') {
const schemaDocs = this.findChildrenByLocalName(child, 'schemaDocument');
if (schemaDocs.length === 0) {
continue;
}
const expectedEl = this.findChildByLocalName(child, 'expected');
const expected = expectedEl?.getAttribute('validity')?.getValue() || 'valid';
const testName = child.getAttribute('name')?.getValue() || groupName;
let actual = 'valid';
outer: try {
for (const schemaDocEl of schemaDocs) {
const href = this.getXlinkHref(schemaDocEl);
if (!href) {
continue;
}
const schemaPath = (0, node_path_1.resolve)(testSetDir, href);
if (!(0, node_fs_1.existsSync)(schemaPath)) {
continue;
}
const parser = new SAXParser_js_1.SAXParser();
const handler = new DOMBuilder_js_1.DOMBuilder();
parser.setContentHandler(handler);
parser.parseFile(schemaPath);
const schemaRoot = handler.getDocument()?.getRoot();
if (schemaRoot) {
XSDSemanticValidator_js_1.XSDSemanticValidator.validate(schemaRoot);
}
}
}
catch (_e) {
actual = 'invalid';
}
stats.total++;
if (actual === expected) {
stats.passed++;
}
else if (!this.isAccepted(child)) {
stats.skipped++;
}
else {
stats.failed++;
console.log(' -- ' + testName + ': expected=' + expected + ' actual=' + actual);
}
continue;
}
// ---- instanceTest ----
// Boeing instance files declare their grammar via
// xsi:schemaLocation with a relative path (e.g. "ipo.xsd"),
// resolved relative to the instance file's own directory.
// SAXParser + setValidating(true) handles this automatically.
if (childLocalName !== 'instanceTest') {
continue;
}
const instanceDocEl = this.findChildByLocalName(child, 'instanceDocument');
if (!instanceDocEl) {
continue;
}
const href = this.getXlinkHref(instanceDocEl);
if (!href) {
continue;
}
const instancePath = (0, node_path_1.resolve)(testSetDir, href);
if (!(0, node_fs_1.existsSync)(instancePath)) {
continue;
}
const expectedEl = this.findChildByLocalName(child, 'expected');
const expected = expectedEl?.getAttribute('validity')?.getValue() || 'valid';
const testName = child.getAttribute('name')?.getValue() || groupName;
let actual;
try {
const parser = new SAXParser_js_1.SAXParser();
const handler = new DOMBuilder_js_1.DOMBuilder();
parser.setContentHandler(handler);
parser.setValidating(true);
parser.parseFile(instancePath);
actual = 'valid';
}
catch (_e) {
actual = 'invalid';
}
stats.total++;
if (actual === expected) {
stats.passed++;
}
else if (!this.isAccepted(child)) {
stats.skipped++;
}
else {
stats.failed++;
console.log(' -- ' + testName + ': expected=' + expected + ' actual=' + actual + ' [' + instancePath + ']');
}
}
}
return stats;
}
parseXML(filePath) {
try {
const parser = new SAXParser_js_1.SAXParser();
const handler = new DOMBuilder_js_1.DOMBuilder();
parser.setContentHandler(handler);
parser.parseFile(filePath);
return handler.getDocument();
}
catch (e) {
return undefined;
}
}
localName(name) {
const idx = name.indexOf(':');
return idx !== -1 ? name.substring(idx + 1) : name;
}
isAccepted(child) {
const currentEl = this.findChildByLocalName(child, 'current');
if (!currentEl) {
return true;
}
const status = currentEl.getAttribute('status')?.getValue();
return status === undefined || status === 'accepted';
}
getXlinkHref(el) {
for (const attr of el.getAttributes()) {
const attrName = attr.getName();
if (attrName === 'xlink:href' || attrName.endsWith(':href')) {
return attr.getValue();
}
}
return undefined;
}
findChildByLocalName(el, localName) {
for (const child of el.getChildren()) {
if (this.localName(child.getName()) === localName) {
return child;
}
}
return undefined;
}
findChildrenByLocalName(el, localName) {
const result = [];
for (const child of el.getChildren()) {
if (this.localName(child.getName()) === localName) {
result.push(child);
}
}
return result;
}
printReport() {
console.log('');
for (const stats of this.setResults) {
const effective = stats.total - stats.skipped;
const pct = effective > 0 ? ((stats.passed / effective) * 100).toFixed(1) : '0.0';
console.log(stats.contributor + ' [' + stats.name + ']: passed=' + stats.passed + ', failed=' + stats.failed + ', skipped=' + stats.skipped + ', total=' + stats.total + ' (' + pct + '%)');
}
const grandEffective = this.grandTotal - this.grandSkipped;
const totalPct = grandEffective > 0 ? ((this.grandPassed / grandEffective) * 100).toFixed(1) : '0.0';
console.log('');
console.log('TOTAL: ' + this.grandPassed + '/' + grandEffective + ' (' + totalPct + '%) - Skipped ' + this.grandSkipped + ' contested tests');
console.log('');
}
}
try {
new XMLSchemaTestSuite().run();
}
catch (error) {
console.error('Error running XML Schema Test Suite:', error);
}
//# sourceMappingURL=XMLSchemaTestSuite.js.map