diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..fa29cdf --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +** \ No newline at end of file diff --git a/src/validator.js b/src/validator.js index 21e4677..43a610a 100644 --- a/src/validator.js +++ b/src/validator.js @@ -50,9 +50,10 @@ const validate = async( xformStr, options = {} ) => { return Promise.resolve( { warnings, errors, version, duration } ); } - + xform.checkStructure( warnings, errors ); xform.checkBinds( warnings, errors ); + xform.checkRelatives( warnings, errors ); xform.checkAppearances( warnings, errors ); if ( options.openclinica ) { diff --git a/src/xform.js b/src/xform.js index fa035c0..e635e2e 100644 --- a/src/xform.js +++ b/src/xform.js @@ -491,6 +491,27 @@ class XForm { .forEach( nodeName => errors.push( `Question "${nodeName}" has a calculation that is not set to readonly.` ) ); } + /** + * NEW! Check to see if there are any relative paths in refs or nodesets. Modifies provided `warnings` and `errors` arrays. + * + * @param {Array} warnings - Array of existing warnings. + * @param {Array} errors - Array of existing errors. + */ + + checkRelatives( warnings, errors ) { + this.formControls.concat( this.groups ).concat( this.repeats ) + .forEach( control => { + const controlNsPrefix = this.nsPrefixResolver( control.namespaceURI ); + const controlName = controlNsPrefix && /:/.test( control.nodeName ) ? controlNsPrefix + ':' + control.nodeName.split( ':' )[ 1 ] : control.nodeName; + const pathAttr = controlName === 'repeat' ? 'nodeset' : 'ref'; + + const val = control.getAttribute(pathAttr); + if (val.startsWith('.')) { + errors.push( `"${controlName}" found with relative path.`) + } + }) +} + /** * Checks if appearances are valid. Modifies provided `warnings` and `errors` arrays. * diff --git a/test/xform/relative-refs.xml b/test/xform/relative-refs.xml new file mode 100644 index 0000000..c1dd207 --- /dev/null +++ b/test/xform/relative-refs.xml @@ -0,0 +1,71 @@ + + + Nested Repeats + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + +