diff --git a/__data__/gml_id.xsd b/__data__/gml_id.xsd
new file mode 100644
index 0000000..4f4c625
--- /dev/null
+++ b/__data__/gml_id.xsd
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/__tests__/XMLValidatior.js b/__tests__/XMLValidatior.js
index 6b02187..6dd4a28 100644
--- a/__tests__/XMLValidatior.js
+++ b/__tests__/XMLValidatior.js
@@ -569,5 +569,44 @@ describe ('sequence', () => {
})
+})
+
+describe ('gml:id attribute ref', () => {
+
+ const xs = new XMLSchemata (Path.join (__dirname, '..', '__data__', 'gml_id.xsd'))
+
+ test ('gml:id accepted on FunctionalZone', () => {
+
+ new XMLParser ({xs}).process ([
+ ``,
+ `8b2457c9-85c4-466a-a14b-b20856527718`,
+ ``,
+ ].join (''))
+
+ })
+
+ test ('bare id rejected (namespace required)', () => {
+
+ expect (() => new XMLParser ({xs}).process ([
+ ``,
+ `8b2457c9-85c4-466a-a14b-b20856527718`,
+ ``,
+ ].join (''))).toThrow ('Unknown attribute')
+
+ })
+
+ test ('wrong namespace rejected', () => {
+
+ expect (() => new XMLParser ({xs}).process ([
+ ``,
+ `8b2457c9-85c4-466a-a14b-b20856527718`,
+ ``,
+ ].join (''))).toThrow ('Unknown attribute')
+
+ })
})
diff --git a/lib/validation/XMLValidationState.js b/lib/validation/XMLValidationState.js
index a85cfb4..706cbdf 100644
--- a/lib/validation/XMLValidationState.js
+++ b/lib/validation/XMLValidationState.js
@@ -116,13 +116,39 @@ class XMLValidationState {
}
+ resolveAttribute (name, attributesMap) {
+
+ const {attributes} = this.anyType
+
+ if (attributes.has (name)) {
+
+ const def = attributes.get (name)
+
+ if (!def.targetNamespace || def.targetNamespace === attributesMap.getNamespaceURI (name)) return def
+
+ }
+
+ const localName = attributesMap.getLocalName (name); if (localName === name) return null
+
+ const def = attributes.get (localName); if (!def) return null
+
+ if (def.targetNamespace !== attributesMap.getNamespaceURI (name)) return null
+
+ return def
+
+ }
+
validateAttributes (attributesMap) {
const {attributes, isAnyAttributeAllowed} = this.anyType
+ const matched = new Set ()
+
for (const [name, value] of attributesMap) {
- if (!attributes.has (name)) {
+ const def = this.resolveAttribute (name, attributesMap)
+
+ if (!def) {
if (isAnyAttributeAllowed) continue
@@ -131,8 +157,10 @@ class XMLValidationState {
throw Error (`Unknown attribute: "${name}"`)
}
-
- const def = attributes.get (name), {attributes: {fixed, type}} = def
+
+ matched.add (def)
+
+ const {attributes: {fixed, type}} = def
if (typeof fixed === 'string' && value !== fixed) throw Error (`The attribute "${name}" must have the value "${fixed}", not "${value}"`)
@@ -164,7 +192,7 @@ class XMLValidationState {
}
- for (const [name, def] of attributes) if (!attributesMap.has (name)) {
+ for (const [name, def] of attributes) if (!matched.has (def)) {
if (def.attributes.use === 'required') throw Error (`Missing required attribute: "${name}"`)