kripken / xml.js

Port of libxml to JavaScript using Emscripten
Other
174 stars 67 forks source link

Import multiple schema files needed for validation #8

Open hubgit opened 9 years ago

hubgit commented 9 years ago

If a schema file imports other modules, they need to be in the same pseudo-filesystem for xmllint to access.

I've had a go at this in https://github.com/hubgit/xml.js/commit/2cbc559b64616e2bbba4d842bdee47b26b32c0a0 (which also includes changes to allow all the command line arguments to be passed into validateXML along with the list of files to be imported, and returns stdout and stderr separately so that the XML in stdout can be used subsequently).

sterpe commented 9 years ago

I'm a bit unclear. Your changes break using xmllint within node.js completely.

I'm also unclear why this API proposal offers over the previous options object?

Edit: Okay I get what you are trying to solve.

If you want to support unsupported command line flags, it seems like you could add support for those flags within the existing API's {options}, or am I missing something? It also seem like we could pass in any schema file imports as an array property there as well.

sterpe commented 9 years ago

To be clear: I'm totally for the capability this provides, but xmllint should still work in node & the solution should extend the existing api in a fully backwards compatible way.

hubgit commented 9 years ago

Basiclaly I'm just trying to make the interface as simple as possible (and in my case this is for a Polymer element, so doesn't need to support node). The aim is to make calling xmllint(args, files) as close as possible to running xmllint [args] file on the command line (except that the schema/DTD files need to be passed in as pairs of filenames and data, as they're not fetched automatically) - that's why this isn't a pull request :)

I managed to simplify the interface down quite a bit in the end, so it's perhaps a bit clearer what's going on now: https://github.com/hubgit/xml.js/blob/dtd-validation/src/wrapper.js https://github.com/hubgit/xml.js/blob/dtd-validation/src/pre.js

sterpe commented 9 years ago

I will look into supporting this capability as well.

Sent from my iPhone

On Apr 20, 2015, at 6:13 AM, Alf Eaton notifications@github.com wrote:

Basiclaly I'm just trying to make the interface as simple as possible (and in my case this is for a Polymer element, so doesn't need to support node). The aim is to make calling xmllint(args, files) as close as possible to running xmllint [args] file on the command line (except that the schema/DTD files used need to be passed in as pairs of filenames and data, as they're not fetched automatically) - that's why this isn't a pull request :)

I managed to simplify the interface down quite a bit in the end, so it's perhaps a bit clearer what's going on now: https://github.com/hubgit/xml.js/blob/dtd-validation/src/wrapper.js https://github.com/hubgit/xml.js/blob/dtd-validation/src/pre.js

— Reply to this email directly or view it on GitHub.

mrft commented 9 years ago

I am trying to use xmllint.js in the browser for validation, but I cannot find a clear explanation on how this should be done in the readme.

This seems related, so I thought I'd add the question here: could you add an explanation, or a clear example to the readme that explains how to use this when you have a schema that imports other schema's?

sterpe commented 9 years ago

I think that @hubgit was trying to solve the schema that imports other schemas in the browser. I was reluctant to pull in those changes because they break the library in node.js. If that's not an issue of concern you might checkout his fork (links above).

Generally, speaking you will need to do some type of transformation to compile & run xml.js in the browser: i.e., webpack, browserify, etc.

hubgit commented 9 years ago

@mrft You can see how I was using xmllint.js to validate against a DTD in this branch (using the version of xml.js linked above). It requires listing all the DTD files that would need to be loaded as imports, and making sure they're all loaded into the pseudo-filesystem in advance.

IceOnFire commented 8 years ago

Hi there, is the project still alive? I see that Microsoft uses xml.js to validate Office add-in schemas (see projects scaffolded with this generator), but apparently it doesn't work properly when the main XSD imports other subschemas.

There seems to be a difference between the native xmllint executable and the JS version:

The same behaviour happens if I put all schemas in the project root, so it should not be related to relative paths.

sterpe commented 8 years ago

@IceOnFire The schema references are not available on the virtual filesystem that emscripten loads from. @hubgit did some work on this above.

ikin77 commented 8 years ago

I found the way to do it, in case anybody needs it:

You have to pass all XSDs in a array list:

var Module = { xml: stringWithXMLToCheck, schema: [xsdString1, xsdString2, .....], };

The main XSD must be the last in the list. You also have to modify all XSDs in imports, in "schemaLocation". If for instance the main XSD imports the first XSD in the list, the value is schemaLocation="file_0.xsd". So, the order in the array must match the values you change in all XSD files.

Best regards!!!!

                var errors = xmllint.validateXML(Module).errors;
IceOnFire commented 8 years ago

Thanks @ikin77, it works! ^_^

I think I'll checkout also @hubgit's fork though, since changing paths on my XSDs gives me the chills.

lapo-luchini commented 5 years ago

It would be nice if it was possible to automatically detect that the requested location was already included in a previous element in the schema array.

lapo-luchini commented 5 years ago

I'm using this work-around to automatically link schemas one another:

const
    reLoc1 = /targetNamespace="([^"]+)"/,
    reLoc2 = /(\bimport\s+namespace="([^"]+)"\s+schemaLocation=")[^"]+/g,
    loc = {};
opts.schema = opts.schema.map((s, idx) => {
    // detect namespace defined by this schema
    const ns = reLoc1.exec(s);
    if (ns)
        loc[ns[1]] = 'file_' + idx + '.xsd';
    // redirect imports of a known schema to the right file
    s = s.replace(reLoc2, (all, base, ns) => {
        const file = loc[ns];
        if (!file) return;
        return base + file;
    });
    return s;
});
hmuus commented 4 years ago

I played around a bit, nice piece of work! I'm wondering where to do different language support as well as more verbose return messages. Looking at the result:

"test.xml:27: element CreDtTm: Schemas validity error : Element '{urn:iso:std:iso:20022:tech:xsd:camt.086.001.01}CreDtTm': '34' is not a valid value of the atomic type '{urn:iso:std:iso:20022:tech:xsd:camt.086.001.01}ISODateTime'. test.xml fails to validate"

I would love to see not just ":27:", but at least ":line 27:". For one liner something like ":position 324:".

I tried to get into the code, but after a day of poking around I give up. Any idea where I can hook in?