Skip to content

xmlRegisterFsInputProviders() won't initialize the library and won't work if it is the first call #51

@veemex

Description

@veemex

I have an issue and I don't exactly know from where ir comes, but I can reproduce it.
My stack is node js 20.17.0, express.js and the issues happens on mac and linux as well.
Wherenver the process restarts the first validation fails finding the proper paths to the imports from the schema, the following calls to the validation works. I had to implement a retry logic to bypass the issue for whenever i push an update to production.
It is either me that misuses the library and the imports, or there is indeed something under the hood on how it initializes or waits for stuff.

const path = require("path");
const fs = require("fs").promises;

async function retry(fn, retries = 3, delay = 1000) {
for (let i = 0; i < retries; i++) {
try {
// Try executing the function
return await fn();
} catch (error) {
if (i === retries - 1) {
// If it's the last attempt, rethrow the error
throw error;
}
// Wait for the specified delay before retrying
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}

async function validateXml(xmlString) {
return await retry(
async () => {
try {
const { XmlDocument, XsdValidator } = await import("libxml2-wasm");
const { xmlRegisterFsInputProviders } = await import("libxml2-wasm/lib/nodejs.mjs");

            xmlRegisterFsInputProviders();

            const schemaDir = path.resolve(__dirname, "..", "configs", "xsd");
            const mainSchemaPath = path.join(schemaDir, "index.xsd");

            // Read the main XSD file as text
            let xsdContent = await fs.readFile(mainSchemaPath, "utf8");

            // Adjust schemaLocation attributes to use absolute paths
            const serializationSchemaPath = path.join(schemaDir, "Serialization.xsd");
            const entitiesSchemaPath = path.join(schemaDir, "Entities.xsd");

            xsdContent = xsdContent.replace(
                /schemaLocation="\.\/Serialization\.xsd"/g,
                `schemaLocation="${serializationSchemaPath}"`
            );
            xsdContent = xsdContent.replace(
                /schemaLocation="\.\/Entities\.xsd"/g,
                `schemaLocation="${entitiesSchemaPath}"`
            );

            // Parse the adjusted XSD content
            const xsdDoc = XmlDocument.fromString(xsdContent, { url: mainSchemaPath });

            // Create a validator from the XSD document
            const validator = XsdValidator.fromDoc(xsdDoc);

            // Handle both single XML string and array of XML strings
            const xmlStrings = Array.isArray(xmlString) ? xmlString : [xmlString];
            const errors = [];

            for (const xmlStr of xmlStrings) {
                const xmlDoc = XmlDocument.fromString(xmlStr);
                try {
                    // Validate the XML document
                    validator.validate(xmlDoc);
                } catch (err) {
                    // Collect validation errors
                    errors.push(err.message);
                } finally {
                    // Dispose of the XML document
                    xmlDoc.dispose();
                }
            }

            // Dispose of the validator and XSD document
            validator.dispose();
            xsdDoc.dispose();

            if (errors.length) {
                throw new Error(`Validation failed: ${errors.join(", ")}`);
            }

            return true;
        } catch (err) {
            console.error("Validation error:", err);
            throw err; // This will trigger the retry
        }
    },
    3,
    150
); // 3 retries, 2000ms delay between attempts

}

module.exports = validateXml;

And the error here:

error:
Validation error:
XmlValidateError: Element '{http://www.w3.org/2001/XMLSchema}element', attribute 'type': References from this schema to components in the namespace 'https://pontaj.s3.eu-central-1.amazonaws.com/Serialization.xsd' are not allowed, since not indicated by an import statement.

at XmlValidateError.fromDetails (file:///.../node_modules/libxml2-wasm/lib/validates.mjs:53:16)
at new XsdValidator (file:///.../node_modules/libxml2-wasm/lib/validates.mjs:158:44)
at XsdValidator.fromDoc (file:///...r/node_modules/libxml2-wasm/lib/validates.mjs:196:28)
at /.../validateXml.js:52:48
at async retry (/.../validateXml.js:8:20)
at async validateXml (/.../validateXml.js:21:12)
at async /.../generareRegistru.js:20:29 {

details: [
{
message: "Element '{http://www.w3.org/2001/XMLSchema}element', attribute 'type': References from this schema to components in the namespace 'https://pontaj.s3.eu-central-1.amazonaws.com/Serialization.xsd' are not allowed, since not indicated by an import statement.\n",
line: 22,
col: 0,
file: '/.../configs/xsd/index.xsd'
}
]
} (validateXml.js:82)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    Status

    Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions