Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module fails when importing an external XSD #11

Open
TrevorMW opened this issue Aug 2, 2016 · 4 comments
Open

Module fails when importing an external XSD #11

TrevorMW opened this issue Aug 2, 2016 · 4 comments

Comments

@TrevorMW
Copy link

TrevorMW commented Aug 2, 2016

This test schema fails at this line
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd" />
while trying to load, and emits warnings and errors like this

I/O warning : failed to load external entity "xml.xsd"
and
Schemas parser error : attribute use (unknown), attribute 'ref': The QName value '{http://www.w3.org/XML/1998/namespace}lang'

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
        xmlns           = "http://www.demandware.com/xml/impex/store/2007-04-30"
        xmlns:xsd       = "http://www.w3.org/2001/XMLSchema"
        targetNamespace = "http://www.demandware.com/xml/impex/store/2007-04-30"
        elementFormDefault = "qualified">

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

    <xsd:element name="stores">
        <xsd:complexType mixed="false">
            <xsd:sequence>
                <xsd:element name="store" type="complexType.Store" minOccurs="0" maxOccurs="unbounded" />
                <xsd:element name="store-group" type="complexType.StoreGroup" minOccurs="0" maxOccurs="unbounded">
                    <xsd:annotation>
                        <xsd:documentation>
                            store-group are part of "DemandwareStore" beta feature. This element will be ignored on import if the feature is not enabled.
                        </xsd:documentation>
                    </xsd:annotation>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

    <!-- Fake some more top level elements to allow for snippet based JAXB parsing -->
    <xsd:element name="store" type="complexType.Store" />
    <xsd:element name="store-group" type="complexType.StoreGroup" />

    <xsd:complexType name="complexType.Store" mixed="false">
        <xsd:sequence>
            <xsd:element name="name" type="simpleType.Generic.String.256" minOccurs="0" maxOccurs="1" />
            <xsd:element name="address1" type="simpleType.Generic.String.256" minOccurs="0" maxOccurs="1" />
            <xsd:element name="address2" type="simpleType.Generic.String.256" minOccurs="0" maxOccurs="1" />
            <xsd:element name="city" type="simpleType.Generic.String.256" minOccurs="0" maxOccurs="1" />
            <xsd:element name="postal-code" type="simpleType.Generic.String.256" minOccurs="0" maxOccurs="1" />
            <xsd:element name="state-code" type="simpleType.Generic.String.256" minOccurs="0" maxOccurs="1" />
            <xsd:element name="country-code" type="simpleType.CountryCode" minOccurs="0" maxOccurs="1" />
            <xsd:element name="email" type="simpleType.Email" minOccurs="0" maxOccurs="1" />
            <xsd:element name="phone" type="simpleType.PhoneNumber" minOccurs="0" maxOccurs="1" />
            <xsd:element name="fax" type="simpleType.PhoneNumber" minOccurs="0" maxOccurs="1" />
            <xsd:element name="store-events" type="sharedType.LocalizedText" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="store-hours" type="sharedType.LocalizedText" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element name="image" type="simpleType.Generic.String.256" minOccurs="0" maxOccurs="1" />
            <xsd:element name="latitude" type="simpleType.Latitude" minOccurs="0" maxOccurs="1" />
            <xsd:element name="longitude" type="simpleType.Longitude" minOccurs="0" maxOccurs="1" />
            <xsd:element name="inventory-list-id" type="simpleType.Generic.NonEmptyString.256" minOccurs="0" maxOccurs="1" />
            <xsd:element name="store-locator-enabled-flag" type="xsd:boolean" minOccurs="0" maxOccurs="1" />
            <xsd:element name="demandware-pos-enabled-flag" type="xsd:boolean" minOccurs="0" maxOccurs="1" />
            <xsd:element name="custom-attributes" type="sharedType.CustomAttributes" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
        <xsd:attribute name="store-id" type="simpleType.Generic.NonEmptyString.256" use="required" />
        <xsd:attribute name="mode" type="simpleType.ImportMode" />
    </xsd:complexType>

    <xsd:complexType name="complexType.StoreGroup" mixed="false">
        <xsd:sequence>
            <xsd:element name="name" type="simpleType.Generic.String.256" minOccurs="0" maxOccurs="1" />
            <xsd:element name="stores" type="complexType.StoreList" minOccurs="0" maxOccurs="1" />
            <xsd:element name="price-books" type="complexType.PriceBookList" minOccurs="0" maxOccurs="1" />
            <xsd:element name="custom-attributes" type="sharedType.CustomAttributes" minOccurs="0" maxOccurs="1" />
        </xsd:sequence>
        <xsd:attribute name="store-group-id" type="simpleType.Generic.NonEmptyString.256" use="required" />
        <xsd:attribute name="mode" type="simpleType.ImportMode" />
    </xsd:complexType>

    <xsd:complexType name="complexType.StoreList" mixed="false">
        <xsd:sequence>
            <xsd:element name="store" type="complexType.StoreAssignment" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="complexType.PriceBookList" mixed="false">
        <xsd:sequence>
            <xsd:element name="price-book" type="complexType.PriceBookAssignment" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="complexType.StoreAssignment" mixed="false">
        <xsd:attribute name="store-id" type="simpleType.Generic.String.256" use="required" />
    </xsd:complexType>

    <xsd:complexType name="complexType.PriceBookAssignment" mixed="false">
        <xsd:attribute name="price-book-id" type="simpleType.Generic.String.256" use="required" />
    </xsd:complexType>

    <!-- Shared Complex Types -->

    <xsd:complexType name="sharedType.LocalizedText" mixed="false">
        <xsd:simpleContent>
            <xsd:extension base="simpleType.Generic.String">
                <xsd:attribute ref="xml:lang" />
            </xsd:extension>
        </xsd:simpleContent>
    </xsd:complexType>

    <xsd:complexType name="sharedType.CustomAttributes" mixed="false">
        <xsd:sequence>
            <xsd:element name="custom-attribute" type="sharedType.CustomAttribute" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="sharedType.CustomAttribute" mixed="true">
        <xsd:sequence>
            <xsd:element name="value" type="simpleType.Generic.String" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
        <xsd:attribute name="attribute-id" type="simpleType.Generic.NonEmptyString.256" use="required" />
        <xsd:attribute ref="xml:lang" />
    </xsd:complexType>

    <!-- Simple Types -->

    <xsd:simpleType name="simpleType.Generic.String">
        <xsd:restriction base="xsd:string" />
    </xsd:simpleType>

    <xsd:simpleType name="simpleType.Generic.String.10">
        <xsd:restriction base="simpleType.Generic.String">
            <xsd:minLength value="0" />
            <xsd:maxLength value="10" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="simpleType.Generic.String.256">
        <xsd:restriction base="simpleType.Generic.String">
            <xsd:minLength value="0" />
            <xsd:maxLength value="256" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="simpleType.Generic.String.4000">
        <xsd:restriction base="simpleType.Generic.String">
            <xsd:minLength value="0" />
            <xsd:maxLength value="4000" />
        </xsd:restriction>
    </xsd:simpleType>

    <!--  Nonempty string with no leading or trailing whitespace -->
    <xsd:simpleType name="simpleType.Generic.NonEmptyString.256">
        <xsd:restriction base="simpleType.Generic.String">
            <xsd:minLength value="1" />
            <xsd:maxLength value="256" />
            <xsd:pattern value="\S|(\S(.*)\S)" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="simpleType.CountryCode">
        <xsd:restriction base="simpleType.Generic.String">
            <xsd:minLength value="2" />
            <xsd:maxLength value="2" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="simpleType.Email">
        <xsd:restriction base="simpleType.Generic.String">
            <xsd:minLength value="0" />
            <xsd:maxLength value="256" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="simpleType.PhoneNumber">
        <xsd:restriction base="simpleType.Generic.String">
            <xsd:minLength value="0" />
            <xsd:maxLength value="256" />
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="simpleType.Latitude">
        <xsd:restriction base="xsd:decimal">
            <xsd:minInclusive value="-90.0"/>
            <xsd:maxInclusive value="+90.0"/>
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="simpleType.Longitude">
        <xsd:restriction base="xsd:decimal">
            <xsd:minInclusive value="-180.0"/>
            <xsd:maxInclusive value="+180.0"/>
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="simpleType.ImportMode">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="delete" />
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

From what I can gather it has something to do with the library not being able to pull in the correct xml:lang definition correctly, possibly due to throttling by the w3c??

any suggestions?

@TrevorMW TrevorMW changed the title Module fails to parse Module fails to provided XSD correctly Aug 2, 2016
@TrevorMW TrevorMW changed the title Module fails to provided XSD correctly Module fails when importing an external XSD Aug 2, 2016
@jrodrguez08
Copy link

I'm seeing this error too

@FennNaten
Copy link

Hi @TrevorMW,
I ran into the same issue (and, funny thing, I was also validating demandware files :) ), then I re-read the doc, and especially the "Import and includes" which states "XSD includes are supported but relative paths must be given from the execution directory"
So, as the includes are relative in the demandware xsds, what I did was:

  • put all the xsd bundle in a directory
  • when loading a xsd from the bundle, use process.chdir(path-to-bundle-directory) right before to (temporarily) make the bundle directory be the execution directory
  • switch back to the initial working directory when xsd loading is done

And this works fine, xsd is loaded with imports.

Dirty example code:

var xsd = require('libxml-xsd');
var path = require('path');
var initialCWD = path.resolve(''); //keeping that to put it back afterwards
process.chdir(path.resolve(__dirname, '../../resources')); //this changes cwd for a directory where I put a metadata.xsd and xml.xsd. metadata.xsd includes xml.xsd
xsd.parseFile(path.resolve('./metadata.xsd'), function (err, schema) {
    if (err) { 
        console.log(err);
        return;
    }
    console.log('loaded');
    process.chdir(initialCWD); //getting cwd back
    schema.validateFile(path.resolve(__dirname, '../../test/metadata-export-20160825.xml'), function(err, validationErrors){
        if (err) {
            console.log(err);
            return;
        }
        if (validationErrors){ 
            console.log(validationErrors);
            return;
        }
  });  
});

What can cause issues is that changing cwd while performing async operations can induce path-related race conditions. If any code relying on cwd executes between xsd.parseFile and its callback execution, things can break (assuming it's really async). A solution may be to delegate the validation code to a separate process.
Hope it helps.

@ainthek
Copy link

ainthek commented Dec 16, 2016

+1 for changing this behavior to follow XSD specs, not custom quirck. PLEASE

IMHO: This is incorrect and unexpected: XSD includes are supported but relative paths must be given from the execution directory, usually the root of the project.

@tiagowippel
Copy link

Hi guys, same problem here...

cf1331 pushed a commit to cf1331/node-libxml-xsd that referenced this issue Mar 20, 2019
The motivation for this change was to correct the behavior of XSD
includes/imports (Issue albanm#11). Paths to included schemas should be resolved
relative to the XSD file, not the execution directory. This was only a
problem for the top level XSD - nested includes were resolved relative to
the files that included them. Setting the `baseUrl` option to the path of
the top level XSD file fixes the unexpected behavior.

Tests have been updated so that they work with includes relative to the
schema files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants