kripken / xml.js

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

failed to load external entity "xml.xsd" #7

Closed koop-bremen closed 9 years ago

koop-bremen commented 9 years ago

Hi,

I've got a problem with the validation of a XML-File.

When trying to validate a XML-File with a Schema-File that references xml.xsd I always get the following error:

warning: failed to load external entity "xml.xsd"
file.xsd:4: element import: Schemas parser warning : Element '{http://www.w3.org/2001/XMLSchema}import': Failed to locate a schema at location 'xml.xsd'. Skipping the import.

I tried to add the xsd file explicitly to schema like so:

var Module = {
    xml: xmlDoc,
    schema: [genericodeXsd, xmlXsd],
    arguments: ['--noout', '--schema', schemaFileName, xmlFileName]
};

This always gives me the following error: Uncaught TypeError: undefined is not a function, xmllint.js:383

When not stating the '--schema' in the arguments at all like so:

var Module = {
    xml: xmlDoc,
    schema: [genericodeXsd, xmlXsd],
    arguments: ['--noout', xmlFileName]
};

I get the following error:

Uncaught Error: Name must not be empty., xmllint.js:120262

Any ideas how to solve this?

sterpe commented 9 years ago

See ./src/pre.js for how to do this. You need to create the xml and xsd as "files" on the virtual fs, I think.

sterpe commented 9 years ago

@koop-bremen, is this issue okay to close?

koop-bremen commented 9 years ago

yes, you can close it. Thanks!

happypennygames commented 3 years ago

Can @koop-bremen or @sterpe elaborate on their solution? I couldn't follow how to solve using src/pre.js. See here for what I've done- https://github.com/w3c/musicxml/issues/420. It's definitely an issue with how I'm trying to use xml.js.

js code: ''' let opts = { xml: 'myfile.musicxml', schema: 'musicxml.xsd', };

let a = xmllint.validateXML(opts);

''' and I modified the musicxml.xsd file import path to just be xml.xsd and xlink.xsd. '''

<xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="xlink.xsd"/>'''

'''

sterpe commented 3 years ago

You need to modify src/pre.js to create the virtual filesystem files under the names referenced in the xsd. Also you need local copies of those files.

happypennygames commented 3 years ago

Do you mean change this line here: https://github.com/kripken/xml.js/blob/master/src/pre.js#L10

from: FS.createDataFile('/', 'file_' + i + '.xsd', Module'intArrayFromString', true, true);

to: FS.createDataFile('http://www.musicxml.org/xsd/', 'file_' + i + '.xsd', Module'intArrayFromString', true, true);

Then recompile everything to get a modified xmllint.js file?

I'm guessing on the root- that's just the suggested root instead of http://www.w3.org/xsd/ by the notes in the musicxml.xsd file "The XML catalog at catalog.xml supports validating against a local copy of this XSD rather than the networked version. To validate with the MusicXML XSD, use a schema URI of "http://www.musicxml.org/xsd/musicxml.xsd""

It seems like there should be some combination of changing the schemaLocation of the musicxml.xsd file and the arguments to xmllint.js such that no edits to this need to be made to the source code- but no?

sterpe commented 3 years ago

pre.js creates a virtual file for all arguments, but the filenames are generic, i.e., file_${i}. You want to reference a file on the filesystem by name, but the name doesn't exist on the virtual file system. So you need to modify pre.js to add the file to the virtual file system under the same name that it is referenced in the schema file.

It seems like there should be some combination of changing the schemaLocation of the musicxml.xsd file and the arguments to xmllint.js such that no edits to this need to be made to the source code- but no?

It would be something like file_${i}.xsd.

happypennygames commented 3 years ago

So you mean:

for (i = 0; i < Module['schema'].length; i++) {
FS.createDataFile('/', 'file_' + i + '.xsd', Module['intArrayFromString'](Module['schema'][i]), true, true);
}

to

FS.createDataFile('/', 'xml.xsd', Module['intArrayFromString'](Module['schema'][i]), true, true);
FS.createDataFile('/', 'xlink.xsd', Module['intArrayFromString'](Module['schema'][i]), true, true);

and

let opts = {
xml: 'myfile.musicxml',
schema: 'musicxml.xsd',
};

and musicxml.xsd then contains

<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/>
<xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="xlink.xsd"/>'''

?

Thank you for the dialogue!

sterpe commented 3 years ago

Something along those lines, yes.