diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DOTypeValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DOTypeValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..4487953f952f4d653236c0242fde293b28704cdb
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DOTypeValidator.java
@@ -0,0 +1,48 @@
+/**
+ *  Copyright (c) 2019 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.nsd;
+
+import org.eclipse.emf.common.util.DiagnosticChain;
+
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.CDC;
+import fr.centralesupelec.edf.riseclipse.iec61850.scl.DOType;
+import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
+
+public class DOTypeValidator {
+
+    private DataAttributePresenceConditionValidator dataAttributePresenceConditionValidator;
+
+    public DOTypeValidator( CDC cdc ) {
+        dataAttributePresenceConditionValidator = DataAttributePresenceConditionValidator.get( cdc );
+    }
+
+    public boolean validateDOType( DOType doType, DiagnosticChain diagnostics ) {
+        AbstractRiseClipseConsole.getConsole().verbose( "[NSD] validateDOType( " + doType.getId() + " )" );
+        dataAttributePresenceConditionValidator.reset();
+        
+        doType
+        .getDA()
+        .stream()
+        .forEach( d -> dataAttributePresenceConditionValidator.addDA( d, diagnostics ));
+      
+        return dataAttributePresenceConditionValidator.validate( doType, diagnostics );
+        
+    }
+
+}
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataAttributePresenceConditionValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataAttributePresenceConditionValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..72238373a8aa1050da791b95fc415471685a864a
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataAttributePresenceConditionValidator.java
@@ -0,0 +1,1237 @@
+/**
+ *  Copyright (c) 2019 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.nsd;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map.Entry;
+
+import org.eclipse.emf.common.util.BasicDiagnostic;
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.common.util.DiagnosticChain;
+
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.CDC;
+import fr.centralesupelec.edf.riseclipse.iec61850.scl.DA;
+import fr.centralesupelec.edf.riseclipse.iec61850.scl.DOType;
+import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.RiseClipseValidatorSCL;
+import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
+import fr.centralesupelec.edf.riseclipse.util.IRiseClipseConsole;
+
+public class DataAttributePresenceConditionValidator {
+    
+    private static HashMap< String, DataAttributePresenceConditionValidator > validators = new HashMap<>();
+    
+    public static DataAttributePresenceConditionValidator get( CDC cdc ) {
+        if( ! validators.containsKey( cdc.getName() )) {
+            validators.put( cdc.getName(), new DataAttributePresenceConditionValidator( cdc ));
+        }
+        return validators.get( cdc.getName() );
+    }
+    
+    private CDC cdc;
+    
+    // Name of the DataAttribute/DA, DA
+    private HashMap< String, DA > presentDA = new HashMap<>();
+    
+    private HashSet< String > mandatory;
+    private HashSet< String > optional;
+    private HashSet< String > forbidden;
+//    private HashSet< String > notApplicable;
+//    private HashSet< String > mandatoryMulti;
+//    private HashSet< String > optionalMulti;
+    private HashMap< Integer, HashSet< String > > atLeastOne;
+    private HashSet< String > atMostOne;
+    private HashMap< Integer, HashSet< String > > allOrNonePerGroup;
+    private HashMap< Integer, HashSet< String > > allOnlyOneGroup;
+    private HashMap< Integer, HashSet< String > > allAtLeastOneGroup;
+    private HashMap< String, String > mandatoryIfSiblingPresentElseForbidden;
+    private HashMap< String, String > mandatoryIfSiblingPresentElseOptional;
+    private HashMap< String, String > optionalIfSiblingPresentElseMandatory;
+    private HashMap< String, String > forbiddenIfSiblingPresentElseMandatory;
+    private HashMap< String, String > mandatoryIfTextConditionElseOptional;
+    private HashMap< String, String > mandatoryIfTextConditionElseForbidden;
+    private HashMap< String, String > optionalIfTextConditionElseForbidden;
+//    private HashMap< String, Pair< Integer, Integer > > mandatoryMultiRange;
+//    private HashMap< String, Pair< Integer, Integer > > optionalMultiRange;
+//    private HashSet< String > mandatoryIfSubstitutionElseForbidden;
+//    private HashSet< String > mandatoryInLLN0ElseOptional;
+//    private HashSet< String > mandatoryInLLN0ElseForbidden;
+//    private HashSet< String > mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional;
+//    private HashSet< String > mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional;
+//    private HashSet< String > mandatoryIfAnalogValueIncludesIElseForbidden;
+//    private HashSet< String > mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden;
+//    private HashSet< String > mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden;
+//    private HashSet< String > mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional;
+//    private HashSet< String > mandatoryInRootLogicalDeviceElseOptional;
+//    private HashSet< String > mandatoryIfControlSupportsTimeElseOptional;
+//    private HashMap< String, String > oneOrMoreIfSiblingPresentElseForbidden;
+//    private HashSet< String > mandatoryIfControlSupportsSecurity1ElseOptional;
+//    private HashSet< String > mandatoryIfControlSupportsSecurity2ElseOptional;
+    private HashMap< String, String > optionalIfSiblingPresentElseForbidden;
+//    private HashSet< String > mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2;
+//    private HashSet< String > mandatoryIfMeasuredValueExposesRange;
+//    private HashSet< String > optionalIfPhsRefIsSynchrophasorElseMandatory;
+    
+    private final IRiseClipseConsole console = AbstractRiseClipseConsole.getConsole();
+    
+    public DataAttributePresenceConditionValidator( CDC cdc ) {
+        this.cdc = cdc;
+        
+        cdc
+        .getDataAttribute()
+        .stream()
+        .forEach( da -> addSpecification( da.getName(), da.getPresCond(), da.getPresCondArgs() ) );
+
+        checkSpecification();
+    }
+    
+    public void reset() {
+        for( String do_ : presentDA.keySet() ) {
+            presentDA.put( do_, null );
+        }
+    }
+    
+    private void addSpecification( String name, String presCond, String presCondArgs ) {
+        if( presentDA.containsKey( name )) {
+            console.warning( "[NSD setup] " + name + " has already been added to DataAttributePresenceConditionValidator" );
+            return;
+        }
+        presentDA.put( name, null );
+
+        switch( presCond ) {
+        case "M" :
+            // Element is mandatory
+            if( mandatory == null ) mandatory = new HashSet<>();
+            mandatory.add( name );
+            break;
+        case "O" :
+            // Element is optional
+            if( optional == null ) optional = new HashSet<>();
+            optional.add( name );
+            break;
+        case "F" :
+            // Element is forbidden
+            if( forbidden == null ) forbidden = new HashSet<>();
+            forbidden.add( name );
+            break;
+        case "na" :
+            // Element is not applicable
+            // -> TODO: what does it mean ? what do we have to check ?
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"na\" in PresenceCondition" );
+//            if( notApplicable == null ) notApplicable = new HashSet<>();
+//            notApplicable.add( name );
+            break;
+        case "Mmulti" :
+            // At least one element shall be present; all instances have an instance number > 0
+            // -> TODO: not sure what is the instance number, it is assumed to be the suffix of DO name
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"Mmulti\" in PresenceCondition" );
+//            if( mandatoryMulti == null ) mandatoryMulti = new HashSet<>();
+//            mandatoryMulti.add( name );
+            break;
+        case "Omulti" :
+            // Zero or more elements may be present; all instances have an instance number > 0
+            // -> TODO: not sure what is the instance number, it is assumed to be the suffix of DO name
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"Omulti\" in PresenceCondition" );
+//            if( optionalMulti == null ) optionalMulti = new HashSet<>();
+//            optionalMulti.add( name );
+            break;
+        case "AtLeastOne" :
+            // Parameter n: group number (> 0).
+            // At least one of marked elements of a group n shall be present
+            if( atLeastOne == null ) atLeastOne = new HashMap<>();
+            try {
+                Integer arg = Integer.valueOf( presCondArgs );
+                if( arg <= 0 ) {
+                    console.warning( "[NSD setup] argument of PresenceCondition \"AtLeastOne\" is not a positive integer" );
+                    break;
+                }
+                if( ! atLeastOne.containsKey( arg )) {
+                    atLeastOne.put( arg, new HashSet<>() );
+                }
+                atLeastOne.get( arg ).add( name );
+                break;
+            }
+            catch( NumberFormatException e ) {
+                console.warning( "[NSD setup] argument of PresenceCondition \"AtLeastOne\" is not an integer" );
+                break;
+            }
+        case "AtMostOne" :
+            // At most one of marked elements shall be present
+            if( atMostOne == null ) atMostOne = new HashSet<>();
+            atMostOne.add( name );
+            break;
+        case "AllOrNonePerGroup" :
+            // Parameter n: group number (> 0).
+            // All or none of the elements of a group n shall be present
+            if( allOrNonePerGroup == null ) allOrNonePerGroup = new HashMap<>();
+            try {
+                Integer arg = Integer.valueOf( presCondArgs );
+                if( arg <= 0 ) {
+                    console.warning( "[NSD setup] argument of PresenceCondition \"AllOrNonePerGroup\" is not a positive integer" );
+                    break;
+                }
+                if( ! allOrNonePerGroup.containsKey( arg )) {
+                    allOrNonePerGroup.put( arg, new HashSet<>() );
+                }
+                allOrNonePerGroup.get( arg ).add( name );
+                break;
+            }
+            catch( NumberFormatException e ) {
+                console.warning( "[NSD setup] argument of PresenceCondition \"AllOrNonePerGroup\" is not an integer" );
+                break;
+            }
+        case "AllOnlyOneGroup" :
+            // Parameter n: group number (> 0).
+            // All elements of only one group n shall be present
+            if( allOnlyOneGroup == null ) allOnlyOneGroup = new HashMap<>();
+            try {
+                Integer arg = Integer.valueOf( presCondArgs );
+                if( arg <= 0 ) {
+                    console.warning( "[NSD setup] argument of PresenceCondition \"AllOnlyOneGroup\" is not a positive integer" );
+                    break;
+                }
+                if( ! allOnlyOneGroup.containsKey( arg )) {
+                    allOnlyOneGroup.put( arg, new HashSet<>() );
+                }
+                allOnlyOneGroup.get( arg ).add( name );
+                break;
+            }
+            catch( NumberFormatException e ) {
+                console.warning( "[NSD setup] argument of PresenceCondition \"AllOnlyOneGroup\" is not an integer" );
+                break;
+            }
+        case "AllAtLeastOneGroup" :
+            // Parameter n: group number (> 0).
+            // All elements of at least one group n shall be present
+            if( allAtLeastOneGroup == null ) allAtLeastOneGroup = new HashMap<>();
+            try {
+                Integer arg = Integer.valueOf( presCondArgs );
+                if( arg <= 0 ) {
+                    console.warning( "[NSD setup] argument of PresenceCondition \"AllAtLeastOneGroup\" is not a positive integer" );
+                    break;
+                }
+                if( ! allAtLeastOneGroup.containsKey( arg )) {
+                    allAtLeastOneGroup.put( arg, new HashSet<>() );
+                }
+                allAtLeastOneGroup.get( arg ).add( name );
+                break;
+            }
+            catch( NumberFormatException e ) {
+                console.warning( "[NSD setup] argument of PresenceCondition \"AllAtLeastOneGroup\" is not an integer" );
+                break;
+            }
+        case "MF" :
+            // Parameter sibling: sibling element name.
+            // Mandatory if sibling element is present, otherwise forbidden
+            if( mandatoryIfSiblingPresentElseForbidden == null ) mandatoryIfSiblingPresentElseForbidden = new HashMap<>();
+            mandatoryIfSiblingPresentElseForbidden.put( name, presCondArgs );
+            break;
+        case "MO" :
+            // Parameter sibling: sibling element name.
+            // Mandatory if sibling element is present, otherwise optional
+            if( mandatoryIfSiblingPresentElseOptional == null ) mandatoryIfSiblingPresentElseOptional = new HashMap<>();
+            mandatoryIfSiblingPresentElseOptional.put( name, presCondArgs );
+            break;
+        case "OM" :
+            // Parameter sibling: sibling element name.
+            // Optional if sibling element is present, otherwise mandatory
+            if( optionalIfSiblingPresentElseMandatory == null ) optionalIfSiblingPresentElseMandatory = new HashMap<>();
+            optionalIfSiblingPresentElseMandatory.put( name, presCondArgs );
+            break;
+        case "FM" :
+            // Parameter sibling: sibling element name.
+            // Forbidden if sibling element is present, otherwise mandatory
+            if( forbiddenIfSiblingPresentElseMandatory == null ) forbiddenIfSiblingPresentElseMandatory = new HashMap<>();
+            forbiddenIfSiblingPresentElseMandatory.put( name, presCondArgs );
+            break;
+        case "MOcond" :
+            // Parameter condID: condition number (> 0).
+            // Textual presence condition (non-machine processable) with reference condID to context specific text.
+            // If satisfied, the element is mandatory, otherwise optional
+            if( mandatoryIfTextConditionElseOptional == null ) mandatoryIfTextConditionElseOptional = new HashMap<>();
+            try {
+                Integer arg = Integer.valueOf( presCondArgs );
+                if( arg <= 0 ) {
+                    console.warning( "[NSD setup] argument of PresenceCondition \"MOcond\" is not a positive integer" );
+                    break;
+                }
+                mandatoryIfTextConditionElseOptional.put( name, presCondArgs );
+                break;
+            }
+            catch( NumberFormatException e ) {
+                console.warning( "[NSD setup] argument of PresenceCondition \"MOcond\" is not an integer" );
+                break;
+            }
+        case "MFcond" :
+            // Parameter condID: condition number (> 0).
+            // Textual presence condition (non-machine processable) with reference condID to context specific text.
+            // If satisfied, the element is mandatory, otherwise forbidden
+            if( mandatoryIfTextConditionElseForbidden == null ) mandatoryIfTextConditionElseForbidden = new HashMap<>();
+            try {
+                Integer arg = Integer.valueOf( presCondArgs );
+                if( arg <= 0 ) {
+                    console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not a positive integer" );
+                    break;
+                }
+                mandatoryIfTextConditionElseForbidden.put( name, presCondArgs );
+                break;
+            }
+            catch( NumberFormatException e ) {
+                console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not an integer" );
+                break;
+            }
+        case "OFcond" :
+            // Parameter condID: condition number (> 0).
+            // Textual presence condition (non-machine processable) with reference condID to context specific text.
+            // If satisfied, the element is optional, otherwise forbidden
+            if( optionalIfTextConditionElseForbidden == null ) optionalIfTextConditionElseForbidden = new HashMap<>();
+            try {
+                Integer arg = Integer.valueOf( presCondArgs );
+                if( arg <= 0 ) {
+                    console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not a positive integer" );
+                    break;
+                }
+                optionalIfTextConditionElseForbidden.put( name, presCondArgs );
+                break;
+            }
+            catch( NumberFormatException e ) {
+                console.warning( "[NSD setup] argument of PresenceCondition \"MFcond\" is not an integer" );
+                break;
+            }
+        case "MmultiRange" :
+            // Parameters min, max: limits for instance number (> 0).
+            // One or more elements shall be present; all instances have an instance number within range [min, max] (see IEC 61850-7-1)
+            // -> TODO: not sure what is the instance number, it is assumed to be the suffix of DO name
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MmultiRange\" in PresenceCondition" );
+//            if( mandatoryMultiRange == null ) mandatoryMultiRange = new HashMap<>();
+//            String[] limits1 = presCondArgs.split( "[ ,]+" );
+//            if( limits1.length != 2 ) {
+//                console.warning( "[NSD setup] argument of PresenceCondition \"MmultiRange\" is not two integers" );
+//                break;
+//            }
+//            Integer min1 = Integer.valueOf( limits1[0] );
+//            if( min1 <= 0 ) {
+//                console.warning( "[NSD setup] first argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
+//                break;
+//            }
+//            Integer max1 = Integer.valueOf( limits1[1] );
+//            if( max1 <= 0 ) {
+//                console.warning( "[NSD setup] second argument of PresenceCondition \"MmultiRange\" is not a positive integer" );
+//                break;
+//            }
+//            mandatoryMultiRange.put( name, Pair.of( min1, max1 ));
+            break;
+        case "OmultiRange" :
+            // Parameters min, max: limits for instance number (> 0).
+            // Zero or more elements may be present; all instances have an instance number within range [min, max] (see IEC 61850-7-1)
+            // -> TODO: not sure what is the instance number, it is assumed to be the suffix of DO name
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"OmultiRange\" in PresenceCondition" );
+//            if( optionalMultiRange == null ) optionalMultiRange = new HashMap<>();
+//            String[] limits2 = presCondArgs.split( "[ ,]+" );
+//            if( limits2.length != 2 ) {
+//                console.warning( "[NSD setup] argument of PresenceCondition \"OmultiRange\" is not two integers" );
+//                break;
+//            }
+//            Integer min2 = Integer.valueOf( limits2[0] );
+//            if( min2 <= 0 ) {
+//                console.warning( "[NSD setup] first argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
+//                break;
+//            }
+//            Integer max2 = Integer.valueOf( limits2[1] );
+//            if( max2 <= 0 ) {
+//                console.warning( "[NSD setup] second argument of PresenceCondition \"OmultiRange\" is not a positive integer" );
+//                break;
+//            }
+//            optionalMultiRange.put( name, Pair.of( min2, max2 ));
+            break;
+        case "MFsubst" :
+            // Element is mandatory if substitution is supported (for substitution, see IEC 61850-7-3), otherwise forbidden
+            // TODO: how do we know if substitution is supported ?
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MFsubst\" in PresenceCondition" );
+//            if( mandatoryIfSubstitutionElseForbidden == null ) mandatoryIfSubstitutionElseForbidden = new HashSet<>();
+//            mandatoryIfSubstitutionElseForbidden.add( name );
+            break;
+        case "MOln0" :
+            // Element is mandatory in the context of LLN0; otherwise optional
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MOln0\" in PresenceCondition" );
+//            if( mandatoryInLLN0ElseOptional == null ) mandatoryInLLN0ElseOptional = new HashSet<>();
+//            mandatoryInLLN0ElseOptional.add( name );
+            break;
+        case "MFln0" :
+            // Element is mandatory in the context of LLN0; otherwise forbidden
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MFln0\" in PresenceCondition" );
+//            if( mandatoryInLLN0ElseForbidden == null ) mandatoryInLLN0ElseForbidden = new HashSet<>();
+//            mandatoryInLLN0ElseForbidden.add( name );
+            break;
+        case "MOlnNs" :
+            // Element is mandatory if the name space of its logical node deviates from the name space of the containing
+            // logical device, otherwise optional. See IEC 61850-7-1 for use of name space
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MOlnNs\" in PresenceCondition" );
+//            if( mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional == null ) mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional = new HashSet<>();
+//            mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional.add( name );
+            break;
+        case "MOdataNs" :
+            // Element is mandatory if the name space of its data object deviates from the name space of its logical node,
+            // otherwise optional. See IEC 61850-7-1 for use of name space
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MOdataNs\" in PresenceCondition" );
+//            if( mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional == null ) mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional = new HashSet<>();
+//            mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional.add( name );
+            break;
+        case "MFscaledAV" :
+            // Element is mandatory* if any sibling elements of type AnalogueValue include 'i' as a child, otherwise forbidden.
+            // *Even though devices without floating point capability cannot exchange floating point values through ACSI services,
+            // the description of scaling remains mandatory for their (SCL) configuration
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MFscaledAV\" in PresenceCondition" );
+//            if( mandatoryIfAnalogValueIncludesIElseForbidden == null ) mandatoryIfAnalogValueIncludesIElseForbidden = new HashSet<>();
+//            mandatoryIfAnalogValueIncludesIElseForbidden.add( name );
+            break;
+        case "MFscaledMagV" :
+            // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'mag' attribute, otherwise forbidden.
+            // *See MFscaledAV
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MFscaledMagV\" in PresenceCondition" );
+//            if( mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden == null ) mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden = new HashSet<>();
+//            mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden.add( name );
+            break;
+        case "MFscaledAngV" :
+            // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'ang' attribute, otherwise forbidden.
+            // *See MFscaledAV
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MFscaledAngV\" in PresenceCondition" );
+//            if( mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden == null ) mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden = new HashSet<>();
+//            mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden.add( name );
+            break;
+        case "MOrms" :
+            // Element is mandatory if the harmonic values in the context are calculated as a ratio to RMS value
+            // (value of data attribute 'hvRef' is 'rms'), optional otherwise
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MOrms\" in PresenceCondition" );
+//            if( mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional == null ) mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional = new HashSet<>();
+//            mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional.add( name );
+            break;
+        case "MOrootLD" :
+            // Element is mandatory in the context of a root logical device; otherwise it is optional
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MOrootLD\" in PresenceCondition" );
+//            if( mandatoryInRootLogicalDeviceElseOptional == null ) mandatoryInRootLogicalDeviceElseOptional = new HashSet<>();
+//            mandatoryInRootLogicalDeviceElseOptional.add( name );
+            break;
+        case "MOoperTm" :
+            // Element is mandatory if at least one controlled object on the IED supports time activation service; otherwise it is optional
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MOoperTm\" in PresenceCondition" );
+//            if( mandatoryIfControlSupportsTimeElseOptional == null ) mandatoryIfControlSupportsTimeElseOptional = new HashSet<>();
+//            mandatoryIfControlSupportsTimeElseOptional.add( name );
+            break;
+        case "MmultiF" :
+            // Parameter sibling: sibling element name.
+            // One or more elements must be present if sibling element is present, otherwise forbidden
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MmultiF\" in PresenceCondition" );
+//            if( oneOrMoreIfSiblingPresentElseForbidden == null ) oneOrMoreIfSiblingPresentElseForbidden = new HashMap<>();
+//            oneOrMoreIfSiblingPresentElseForbidden.put( name, presCondArgs );
+            break;
+        case "MOsbo" :
+            // Element is mandatory if declared control model supports 'sbo-with-normal-security' or 'sbo-with-enhanced-security',
+            // otherwise optional and value is of no impact
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MOsbo\" in PresenceCondition" );
+//            if( mandatoryIfControlSupportsSecurity1ElseOptional == null ) mandatoryIfControlSupportsSecurity1ElseOptional = new HashSet<>();
+//            mandatoryIfControlSupportsSecurity1ElseOptional.add( name );
+            break;
+        case "MOenhanced" :
+            // Element is mandatory if declared control model supports 'direct-with-enhanced-security' or 'sbo-with-enhanced-security',
+            // otherwise optional and value is of no impact
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MOenhanced\" in PresenceCondition" );
+//            if( mandatoryIfControlSupportsSecurity2ElseOptional == null ) mandatoryIfControlSupportsSecurity2ElseOptional = new HashSet<>();
+//            mandatoryIfControlSupportsSecurity2ElseOptional.add( name );
+            break;
+        case "MONamPlt" :
+            // Element is mandatory if the name space of its logical node deviates from the name space of the containing
+            // logical device, otherwise optional. See IEC 61850-7-1 for use of name space
+            // TODO: same as "MOlnNs" ?
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MONamPlt\" in PresenceCondition" );
+//            if( mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2 == null ) mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2 = new HashSet<>();
+//            mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2.add( name );
+            break;
+        case "OF" :
+            // Parameter sibling: sibling element name.
+            // Optional if sibling element is present, otherwise forbidden
+            if( optionalIfSiblingPresentElseForbidden == null ) optionalIfSiblingPresentElseForbidden = new HashMap<>();
+            optionalIfSiblingPresentElseForbidden.put( name, presCondArgs );
+            break;
+        case "MORange" :
+            // Element is mandatory if the measured value associated (amplitude respectively angle) exposes the range eventing
+            // (with the attribute range respectively rangeAng)
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"MORange\" in PresenceCondition" );
+//            if( mandatoryIfMeasuredValueExposesRange == null ) mandatoryIfMeasuredValueExposesRange = new HashSet<>();
+//            mandatoryIfMeasuredValueExposesRange.add( name );
+            break;
+        case "OMSynPh" :
+            // This attribute is optional if value of 'phsRef'' is Synchrophasor otherwise Mandatory]]></Doc>
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataAttribute " + name + " declared as \"OMSynPh\" in PresenceCondition" );
+//            if( optionalIfPhsRefIsSynchrophasorElseMandatory == null ) optionalIfPhsRefIsSynchrophasorElseMandatory = new HashSet<>();
+//            optionalIfPhsRefIsSynchrophasorElseMandatory.add( name );
+            break;
+        default:
+            console.warning( "[NSD setup] the PresenceCondition " + presCond + " of AnyLNClass " + name + " is unknown" );
+            break;
+        }
+        
+    }
+    
+    private void checkSpecification() {
+        // TODO: do we have to check the presence of the sibling in inherited AbstractLNClass ?
+        if( mandatoryIfSiblingPresentElseForbidden != null ) {
+            for( Entry< String, String > e : mandatoryIfSiblingPresentElseForbidden.entrySet() ) {
+                if( ! presentDA.containsKey( e.getValue() )) {
+                    console.warning( "[NSD setup] the sibling of " + e.getKey() + " in PresenceCondition of DataObject " + e.getKey() + " is unknown" );
+                }
+            }
+        }
+        if( mandatoryIfSiblingPresentElseOptional != null ) {
+            for( Entry< String, String > e : mandatoryIfSiblingPresentElseOptional.entrySet() ) {
+                if( ! presentDA.containsKey( e.getValue() )) {
+                    console.warning( "[NSD setup] the sibling of " + e.getKey() + " in PresenceCondition of DataObject " + e.getKey() + " is unknown" );
+                }
+            }
+        }
+        if( optionalIfSiblingPresentElseMandatory != null ) {
+            for( Entry< String, String > e : optionalIfSiblingPresentElseMandatory.entrySet() ) {
+                if( ! presentDA.containsKey( e.getValue() )) {
+                    console.warning( "[NSD setup] the sibling of " + e.getKey() + " in PresenceCondition of DataObject " + e.getKey() + " is unknown" );
+                }
+            }
+        }
+        if( forbiddenIfSiblingPresentElseMandatory != null ) {
+            for( Entry< String, String > e : forbiddenIfSiblingPresentElseMandatory.entrySet() ) {
+                if( ! presentDA.containsKey( e.getValue() )) {
+                    console.warning( "[NSD setup] the sibling of " + e.getKey() + " in PresenceCondition of DataObject " + e.getKey() + " is unknown" );
+                }
+            }
+        }
+//        if( oneOrMoreIfSiblingPresentElseForbidden != null ) {
+//            for( Entry< String, String > e : oneOrMoreIfSiblingPresentElseForbidden.entrySet() ) {
+//                if( ! presentDA.containsKey( e.getValue() )) {
+//                    console.warning( "[NSD setup] the sibling of " + e.getKey() + " in PresenceCondition of DataObject " + e.getKey() + " is unknown" );
+//                }
+//            }
+//        }
+        if( optionalIfSiblingPresentElseForbidden != null ) {
+            for( Entry< String, String > e : optionalIfSiblingPresentElseForbidden.entrySet() ) {
+                if( ! presentDA.containsKey( e.getValue() )) {
+                    console.warning( "[NSD setup] the sibling of " + e.getKey() + " in PresenceCondition of DataObject " + e.getKey() + " is unknown" );
+                }
+            }
+        }
+    }
+
+    public boolean addDA( DA da, DiagnosticChain diagnostics ) {
+        if( ! presentDA.containsKey( da.getName() )) {
+            diagnostics.add( new BasicDiagnostic(
+                    Diagnostic.ERROR,
+                    RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                    0,
+                    "[NSD validation] DA " + da.getName() + " in DOType (line " + da.getParentDOType().getLineNumber() + ") not found in CDC " + cdc.getName(),
+                    new Object[] { da } ));
+            return false;
+        }
+
+        if( presentDA.get( da.getName() ) != null ) {
+            diagnostics.add( new BasicDiagnostic(
+                    Diagnostic.ERROR,
+                    RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                    0,
+                    "[NSD validation] DA " + da.getName() + " in DOType (line " + da.getParentDOType().getLineNumber() + ") already present in CDC " + cdc.getName(),
+                    new Object[] { da } ));
+            return false;
+        }
+        presentDA.put( da.getName(), da );
+        return true;
+    }
+    
+    public boolean validate( DOType doType, DiagnosticChain diagnostics ) {
+        boolean res = true;
+        
+        // presCond: "M"
+        // Element is mandatory
+        // Usage in standard NSD files (version 2007B): DataObject and DataAttribute and SubDataAttribute
+        if( mandatory != null ) {
+            for( String name : this.mandatory ) {
+                if( presentDA.get( name ) == null ) {
+                  diagnostics.add( new BasicDiagnostic(
+                          Diagnostic.ERROR,
+                          RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                          0,
+                          "[NSD validation] DA " + name + " is mandatory in DOType (line " + doType.getLineNumber() + ") with CDC " + cdc.getName(),
+                          new Object[] { doType } ));
+                  res = false;
+                }
+            }
+        }
+
+        // presCond: "O"
+        // Element is optional
+        // Usage in standard NSD files (version 2007B): DataObject and DataAttribute and SubDataAttribute
+        if( optional != null ) {
+            for( String name : this.optional ) {
+                if( presentDA.get( name ) == null ) {
+                    // Nothing
+                }
+            }
+        }
+
+        // presCond: "F"
+        // Element is forbidden
+        // Usage in standard NSD files (version 2007B): DataObject
+        if( forbidden != null ) {
+            for( String name : this.forbidden ) {
+                if( presentDA.get( name ) != null ) {
+                  diagnostics.add( new BasicDiagnostic(
+                          Diagnostic.ERROR,
+                          RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                          0,
+                          "[NSD validation] DA " + name + " is forbidden in DOType (line " + doType.getLineNumber() + ") with CDC " + cdc.getName(),
+                          new Object[] { doType } ));
+                  res = false;
+                }
+            }
+        }
+
+        // presCond: "na"
+        // Element is not applicable
+        // Usage in standard NSD files (version 2007B): only for dsPresCond
+        // -> TODO: what does it mean ? what do we have to check ?
+//        if( notApplicable != null ) {
+//
+//        }
+        
+        // presCond: "Mmulti"
+        // At least one element shall be present; all instances have an instance number > 0
+        // Usage in standard NSD files (version 2007B): DataObject
+//        if( mandatoryMulti != null ) {
+//
+//        }
+
+        // presCond: "Omulti"
+        // Zero or more elements may be present; all instances have an instance number > 0
+        // Usage in standard NSD files (version 2007B): DataObject
+//        if( optionalMulti != null ) {
+//
+//        }
+        
+        // presCond: "AtLeastOne"
+        // Parameter n: group number (> 0).
+        // At least one of marked elements of a group n shall be present
+        // Usage in standard NSD files (version 2007B): DataObject and SubDataObject and DataAttribute and SubDataAttribute
+        if( atLeastOne != null ) {
+            for( Entry< Integer, HashSet< String > > e1 : atLeastOne.entrySet() ) {
+                boolean groupOK = false;
+                for( String member : e1.getValue() ) {
+                    if( presentDA.get( member ) != null ) {
+                        groupOK = true;
+                        break;
+                    }
+                }
+                if( ! groupOK ) {
+                    diagnostics.add( new BasicDiagnostic(
+                            Diagnostic.ERROR,
+                            RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                            0,
+                            "[NSD validation] group " + e1.getKey() + " has no elements in DOType (line " + doType.getLineNumber() + ") with CDC " + cdc.getName(),
+                            new Object[] { doType } ));
+                    res = false;
+                }
+            }
+        }
+        
+        // presCond: "AtMostOne" :
+        // At most one of marked elements shall be present
+        // Usage in standard NSD files (version 2007B): DataObject
+        if( atMostOne != null ) {
+            int count = 0;
+            for( String s : atMostOne ) {
+                if( presentDA.get( s ) != null ) {
+                    ++count;
+                }
+            }
+            if( count > 1 ) {
+                diagnostics.add( new BasicDiagnostic(
+                        Diagnostic.ERROR,
+                        RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                        0,
+                        "[NSD validation] LNodeType (line " + doType.getLineNumber() + ") with CDC " + cdc.getName() + " has more than one element marked AtMostOne",
+                        new Object[] { doType } ));
+                res = false;
+            }
+        }
+        
+        // presCond: "AllOrNonePerGroup" :
+        // Parameter n: group number (> 0).
+        // All or none of the elements of a group n shall be present
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        if( allOrNonePerGroup != null ) {
+            for( Entry< Integer, HashSet< String > > e1 : allOrNonePerGroup.entrySet() ) {
+                int groupCount = 0;
+                for( String member : e1.getValue() ) {
+                    if( presentDA.get( member ) != null ) {
+                        ++groupCount;
+                    }
+                }
+                if(( groupCount > 0 ) && (groupCount < e1.getValue().size() )) {
+                    diagnostics.add( new BasicDiagnostic(
+                            Diagnostic.ERROR,
+                            RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                            0,
+                            "[NSD validation] group " + e1.getKey() + " has neither none nor all elements in DOType (line " + doType.getLineNumber() + ") with CDC " + cdc.getName(),
+                            new Object[] { doType } ));
+                    res = false;
+                }
+            }
+        }
+        
+        // presCond: "AllOnlyOneGroup" :
+        // Parameter n: group number (> 0).
+        // All elements of only one group n shall be present
+        // Usage in standard NSD files (version 2007B): DataObject and SubDataAttribute
+        if( allOnlyOneGroup != null ) {
+            int groupNumber = 0;
+            for( Entry< Integer, HashSet< String > > e1 : allOnlyOneGroup.entrySet() ) {
+                int groupCount = 0;
+                for( String member : e1.getValue() ) {
+                    if( presentDA.get( member ) != null ) {
+                        ++groupCount;
+                    }
+                }
+                if(( groupCount > 0 ) && (groupCount < e1.getValue().size() )) {
+                    diagnostics.add( new BasicDiagnostic(
+                            Diagnostic.ERROR,
+                            RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                            0,
+                            "[NSD validation] group " + e1.getKey() + " has neither none nor all elements in DOType (line " + doType.getLineNumber() + ") with CDC " + cdc.getName(),
+                            new Object[] { doType } ));
+                    res = false;
+                }
+                else if( groupCount > 0 ) {
+                    if( groupNumber == 0 ) {
+                        groupNumber = e1.getKey();
+                    }
+                    else {
+                        diagnostics.add( new BasicDiagnostic(
+                                Diagnostic.ERROR,
+                                RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                                0,
+                                "[NSD validation] LNodeType (line " + doType.getLineNumber() + ") with CDC " + cdc.getName() + " has several groups with all elements",
+                                new Object[] { doType } ));
+                        res = false;
+                    }
+                }
+            }
+            if( groupNumber == 0 ) {
+                diagnostics.add( new BasicDiagnostic(
+                        Diagnostic.ERROR,
+                        RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                        0,
+                        "[NSD validation] no group in DOType (line " + doType.getLineNumber() + ") with CDC " + cdc.getName() + " has all elements",
+                        new Object[] { doType } ));
+                res = false;
+            }
+        }
+        
+        // presCond: "AllAtLeastOneGroup" :
+        // Parameter n: group number (> 0).
+        // All elements of at least one group n shall be present
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        if( allAtLeastOneGroup != null ) {
+            int groupNumber = 0;
+            for( Entry< Integer, HashSet< String > > e1 : allAtLeastOneGroup.entrySet() ) {
+                int groupCount = 0;
+                for( String member : e1.getValue() ) {
+                    if( presentDA.get( member ) != null ) {
+                        ++groupCount;
+                    }
+                }
+                if( groupCount == e1.getValue().size() ) {
+                    groupNumber = e1.getKey();
+                }
+            }
+            if( groupNumber == 0 ) {
+                diagnostics.add( new BasicDiagnostic(
+                        Diagnostic.ERROR,
+                        RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                        0,
+                        "[NSD validation] no group in DOType (line " + doType.getLineNumber() + ") with CDC " + cdc.getName() + " has all elements",
+                        new Object[] { doType } ));
+                res = false;
+            }
+        }
+        
+        // presCond: "MF" :
+        // Parameter sibling: sibling element name.
+        // Mandatory if sibling element is present, otherwise forbidden
+        // Usage in standard NSD files (version 2007B): DataObject
+        if( mandatoryIfSiblingPresentElseForbidden != null ) {
+            for( Entry< String, String > entry : mandatoryIfSiblingPresentElseForbidden.entrySet() ) {
+                if( presentDA.get( entry.getValue() ) != null ) {
+                    if( presentDA.get( entry.getKey() ) == null ) {
+                        diagnostics.add( new BasicDiagnostic(
+                                Diagnostic.ERROR,
+                                RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                                0,
+                                "[NSD validation] DA " + entry.getKey() + " is mandatory in DOType (line " + doType.getLineNumber() + ") with LNClass "
+                                        + cdc.getName() + " because sibling " + entry.getValue() + " is present",
+                                new Object[] { doType } ));
+                        res = false;
+                    }
+                }
+                else {
+                    if( presentDA.get( entry.getKey() ) != null ) {
+                        diagnostics.add( new BasicDiagnostic(
+                                Diagnostic.ERROR,
+                                RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                                0,
+                                "[NSD validation] DA " + entry.getKey() + " is forbidden in DOType (line " + doType.getLineNumber() + ") with LNClass "
+                                        + cdc.getName() + " because sibling " + entry.getValue() + " is not present",
+                                new Object[] { doType } ));
+                        res = false;
+                    }
+                }
+            }
+        }
+        
+        // presCond: "MO" :
+        // Parameter sibling: sibling element name.
+        // Mandatory if sibling element is present, otherwise optional
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        if( mandatoryIfSiblingPresentElseOptional != null ) {
+            for( Entry< String, String > entry : mandatoryIfSiblingPresentElseOptional.entrySet() ) {
+                if( presentDA.get( entry.getValue() ) != null ) {
+                    if( presentDA.get( entry.getKey() ) == null ) {
+                        diagnostics.add( new BasicDiagnostic(
+                                Diagnostic.ERROR,
+                                RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                                0,
+                                "[NSD validation] DA " + entry.getKey() + " is mandatory in DOType (line " + doType.getLineNumber() + ") with LNClass "
+                                        + cdc.getName() + " because sibling " + entry.getValue() + " is present",
+                                new Object[] { doType } ));
+                        res = false;
+                    }
+                }
+            }
+        }
+        
+        // presCond: "OM" :
+        // Parameter sibling: sibling element name.
+        // Optional if sibling element is present, otherwise mandatory
+        // Usage in standard NSD files (version 2007B): None
+        if( optionalIfSiblingPresentElseMandatory != null ) {
+            for( Entry< String, String > entry : optionalIfSiblingPresentElseMandatory.entrySet() ) {
+                if( presentDA.get( entry.getValue() ) == null ) {
+                    if( presentDA.get( entry.getKey() ) == null ) {
+                        diagnostics.add( new BasicDiagnostic(
+                                Diagnostic.ERROR,
+                                RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                                0,
+                                "[NSD validation] DA " + entry.getKey() + " is mandatory in DOType (line " + doType.getLineNumber() + ") with LNClass "
+                                        + cdc.getName() + " because sibling " + entry.getValue() + " is not present",
+                                new Object[] { doType } ));
+                        res = false;
+                    }
+                }
+            }
+        }
+        
+        // presCond: "FM" :
+        // Parameter sibling: sibling element name.
+        // Forbidden if sibling element is present, otherwise mandatory
+        // Usage in standard NSD files (version 2007B): None
+        if( forbiddenIfSiblingPresentElseMandatory != null ) {
+            for( Entry< String, String > entry : forbiddenIfSiblingPresentElseMandatory.entrySet() ) {
+                if( presentDA.get( entry.getValue() ) != null ) {
+                    if( presentDA.get( entry.getKey() ) != null ) {
+                        diagnostics.add( new BasicDiagnostic(
+                                Diagnostic.ERROR,
+                                RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                                0,
+                                "[NSD validation] DA " + entry.getKey() + " is forbidden in DOType (line " + doType.getLineNumber() + ") with LNClass "
+                                        + cdc.getName() + " because sibling " + entry.getValue() + " is present",
+                                new Object[] { doType } ));
+                        res = false;
+                    }
+                }
+                else {
+                    if( presentDA.get( entry.getKey() ) == null ) {
+                        diagnostics.add( new BasicDiagnostic(
+                                Diagnostic.ERROR,
+                                RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                                0,
+                                "[NSD validation] DA " + entry.getKey() + " is mandatory in DOType (line " + doType.getLineNumber() + ") with LNClass "
+                                        + cdc.getName() + " because sibling " + entry.getValue() + " is not present",
+                                new Object[] { doType } ));
+                        res = false;
+                    }
+                }
+            }
+        }
+        
+        // presCond: "MOcond" :
+        // Parameter condID: condition number (> 0).
+        // Textual presence condition (non-machine processable) with reference condID to context specific text.
+        // If satisfied, the element is mandatory, otherwise optional
+        // Usage in standard NSD files (version 2007B): DataObject
+        if( mandatoryIfTextConditionElseOptional != null ) {
+            for( Entry< String, String > entry : mandatoryIfTextConditionElseOptional.entrySet() ) {
+                String doc = cdc
+                        .getDataAttribute()
+                        .stream()
+                        .filter( d -> d.getName().equals( entry.getKey() ))
+                        .findFirst()
+                        .map( x -> x.getRefersToPresCondArgsDoc() )
+                        .map( p -> p.getMixed() )
+                        .map( p -> p.get( 0 ) )
+                        .map( p -> p.getValue() )
+                        .map( p -> p.toString() )
+                        .orElse( null );
+
+                diagnostics.add( new BasicDiagnostic(
+                        Diagnostic.WARNING,
+                        RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                        0,
+                        "[NSD validation] DA " + entry.getKey() + " is mandatory in DOType (line " + doType.getLineNumber() + ") with CDC "
+                                + cdc.getName() + " if textual condition number " + entry.getValue() + " (not evaluated) is true, else optional. It is "
+                                + ( presentDA.get( entry.getKey() ) == null ? "absent." : "present." ) + ( doc != null ? " Textual condition is: \"" + doc + "\"." : "" ),
+                        new Object[] { doType } ));
+            }
+        }
+        
+        // presCond: "MFcond" :
+        // Parameter condID: condition number (> 0).
+        // Textual presence condition (non-machine processable) with reference condID to context specific text.
+        // If satisfied, the element is mandatory, otherwise forbidden
+        // Usage in standard NSD files (version 2007B): DataObject
+        if( mandatoryIfTextConditionElseForbidden != null ) {
+            for( Entry< String, String > entry : mandatoryIfTextConditionElseForbidden.entrySet() ) {
+                String doc = cdc
+                        .getDataAttribute()
+                        .stream()
+                        .filter( d -> d.getName().equals( entry.getKey() ))
+                        .findFirst()
+                        .map( x -> x.getRefersToPresCondArgsDoc() )
+                        .map( p -> p.getMixed() )
+                        .map( p -> p.get( 0 ) )
+                        .map( p -> p.getValue() )
+                        .map( p -> p.toString() )
+                        .orElse( null );
+
+                diagnostics.add( new BasicDiagnostic(
+                        Diagnostic.WARNING,
+                        RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                        0,
+                        "[NSD validation] DA " + entry.getKey() + " is mandatory in DOType (line " + doType.getLineNumber() + ") with CDC "
+                                + cdc.getName() + " if textual condition number " + entry.getValue() + " (not evaluated) is true, else forbidden. It is " 
+                                + ( presentDA.get( entry.getKey() ) == null ? "absent." : "present." ) + ( doc != null ? " Textual condition is: \"" + doc + "\"." : "" ),
+                        new Object[] { doType } ));
+            }
+        }
+        
+        // presCond: "OFcond" :
+        // Parameter condID: condition number (> 0).
+        // Textual presence condition (non-machine processable) with reference condID to context specific text.
+        // If satisfied, the element is optional, otherwise forbidden
+        // Usage in standard NSD files (version 2007B): DataObject
+        if( optionalIfTextConditionElseForbidden != null ) {
+            for( Entry< String, String > entry : optionalIfTextConditionElseForbidden.entrySet() ) {
+                String doc = cdc
+                        .getDataAttribute()
+                        .stream()
+                        .filter( d -> d.getName().equals( entry.getKey() ))
+                        .findFirst()
+                        .map( x -> x.getRefersToPresCondArgsDoc() )
+                        .map( p -> p.getMixed() )
+                        .map( p -> p.get( 0 ) )
+                        .map( p -> p.getValue() )
+                        .map( p -> p.toString() )
+                        .orElse( null );
+
+                diagnostics.add( new BasicDiagnostic(
+                        Diagnostic.WARNING,
+                        RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                        0,
+                        "[NSD validation] DA " + entry.getKey() + " is optional in DOType (line " + doType.getLineNumber() + ") with CDC "
+                                + cdc.getName() + " if textual condition number " + entry.getValue() + " (not evaluated) is true, else forbidden. It is " 
+                                + ( presentDA.get( entry.getKey() ) == null ? "absent." : "present." ) + ( doc != null ? " Textual condition is: \"" + doc + "\"." : "" ),
+                        new Object[] { doType } ));
+            }
+        }
+        
+        // presCond: "MmultiRange" :
+        // Parameters min, max: limits for instance number (> 0).
+        // One or more elements shall be present; all instances have an instance number within range [min, max] (see IEC 61850-7-1)
+        // Usage in standard NSD files (version 2007B): None
+//        if( mandatoryMultiRange != null ) {
+//
+//        }
+
+        // presCond: "OmultiRange" :
+        // Parameters min, max: limits for instance number (> 0).
+        // Zero or more elements may be present; all instances have an instance number within range [min, max] (see IEC 61850-7-1)
+        // Usage in standard NSD files (version 2007B): DataObject
+//        if( optionalMultiRange != null ) {
+//
+//        }
+
+        // presCond: "MFsubst" :
+        // Element is mandatory if substitution is supported (for substitution, see IEC 61850-7-3), otherwise forbidden
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO
+//        if( mandatoryIfSubstitutionElseForbidden != null ) {
+//            
+//        }
+        
+        // presCond: "MOln0" :
+        // Element is mandatory in the context of LLN0; otherwise optional
+        // Usage in standard NSD files (version 2007B): DataAttribute
+//        if( mandatoryInLLN0ElseOptional != null ) {
+//
+//        }
+        
+        // presCond: "MFln0" :
+        // Element is mandatory in the context of LLN0; otherwise forbidden
+        // Usage in standard NSD files (version 2007B): DataAttribute
+//        if( mandatoryInLLN0ElseForbidden != null ) {
+//
+//        }
+
+        // presCond: "MOlnNs" :
+        // Element is mandatory if the name space of its logical node deviates from the name space of the containing
+        // logical device, otherwise optional. See IEC 61850-7-1 for use of name space
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO: The meaning is not clear.
+        /*
+        if( mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional != null ) {
+            for( String name : mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional ) {
+                for( AnyLN anyLN : lNodeType.getReferredByAnyLN() ) {
+                    Optional< DOI > namPlt1 =
+                            anyLN
+                            .getDOI()
+                            .stream()
+                            .filter( doi -> "NamPlt".equals( doi.getName() ))
+                            .findFirst();
+                    if( ! namPlt1.isPresent() ) {
+                        console.warning( "[NSD validation] while validating presence condition \"MOlnNs\" of LNodeTYPE  (line " + lNodeType.getLineNumber()
+                                       + ") in AnyLN (line " + anyLN.getLineNumber() + ") : cannot find DOI \"NamPlt\" in AnyLN" );
+                        continue;
+                    }
+                    Optional< DAI > lnNs =
+                            namPlt1
+                            .get()
+                            .getDAI()
+                            .stream()
+                            .filter( dai -> "lnNs".equals( dai.getName() ))
+                            .findFirst();
+                    if( ! lnNs.isPresent() ) {
+                        console.warning( "[NSD validation] while validating presence condition \"MOlnNs\" of LNodeTYPE  (line " + lNodeType.getLineNumber()
+                                       + ") in AnyLN (line " + anyLN.getLineNumber() + ") : cannot find DAI \"lnNs\"" );
+                        continue;
+                    }
+                    if( ! lnNs.get().isSetVal() )  {
+                        console.warning( "[NSD validation] while validating presence condition \"MOlnNs\" of LNodeTYPE  (line " + lNodeType.getLineNumber()
+                                       + ") in AnyLN (line " + anyLN.getLineNumber() + ") : no Val in \"lnNs\"" );
+                        continue;
+                    }
+                    
+                    LN0 ln0 = anyLN.getParentLDevice().getLN0();
+                    Optional< DOI > namPlt2 =
+                            ln0
+                            .getDOI()
+                            .stream()
+                            .filter( doi -> "NamPlt".equals( doi.getName() ))
+                            .findFirst();
+                    if( ! namPlt2.isPresent() ) {
+                        console.warning( "[NSD validation] while validating presence condition \"MOlnNs\" of LNodeTYPE  (line " + lNodeType.getLineNumber()
+                                       + ") in AnyLN (line " + anyLN.getLineNumber() + ") : cannot find DOI \"NamPlt\" in LN0" );
+                        continue;
+                    }
+                    Optional< DAI > ldNs =
+                            namPlt2
+                            .get()
+                            .getDAI()
+                            .stream()
+                            .filter( dai -> "ldNs".equals( dai.getName() ))
+                            .findFirst();
+                    if( ! ldNs.isPresent() ) {
+                        console.warning( "[NSD validation] while validating presence condition \"MOlnNs\" of LNodeTYPE  (line " + lNodeType.getLineNumber()
+                                       + ") in AnyLN (line " + anyLN.getLineNumber() + ") : cannot find DAI \"ldNs\"" );
+                        continue;
+                    }
+                    if( ! ldNs.get().isSetVal() )  {
+                        console.warning( "[NSD validation] while validating presence condition \"MOlnNs\" of LNodeTYPE  (line " + lNodeType.getLineNumber()
+                                       + ") in AnyLN (line " + anyLN.getLineNumber() + ") : no Val in \"ldNs\"" );
+                        continue;
+                    }
+
+                    if( ! ( lnNs.get().getVal().equals( ldNs.get().getVal() ))) {
+                        if( presentDA.get( name ) == null ) {
+                            diagnostics.add( new BasicDiagnostic(
+                                    Diagnostic.ERROR,
+                                    RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                                    0,
+                                    "[NSD validation] DA " + name + " is mandatory in LN in DOType (line " + lNodeType.getLineNumber() + ") with LNClass "
+                                            + cdc.getName() + " because logical node name space deviates from logical device name space",
+                                    new Object[] { lNodeType } ));
+                            res = false;
+                        }
+                    }
+                }
+            }
+        }
+        */
+
+        // presCond: "MOdataNs" :
+        // Element is mandatory if the name space of its data object deviates from the name space of its logical node,
+        // otherwise optional. See IEC 61850-7-1 for use of name space
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO: The meaning is not clear.
+//        if( mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional != null ) {
+//            
+//        }
+
+        // presCond: "MFscaledAV" :
+        // Element is mandatory* if any sibling elements of type AnalogueValue include 'i' as a child, otherwise forbidden.
+        // *Even though devices without floating point capability cannot exchange floating point values through ACSI services,
+        // the description of scaling remains mandatory for their (SCL) configuration
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO
+//        if( mandatoryIfAnalogValueIncludesIElseForbidden != null ) {
+//            
+//        }
+
+        // presCond: "MFscaledMagV" :
+        // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'mag' attribute, otherwise forbidden.
+        // *See MFscaledAV
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO
+//        if( mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden != null ) {
+//        
+//        }
+
+        // presCond: "MFscaledAngV" :
+        // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'ang' attribute, otherwise forbidden.
+        // *See MFscaledAV
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO
+//        if( mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden != null ) {
+//            
+//        }
+
+        // presCond: "MOrms" :
+        // Element is mandatory if the harmonic values in the context are calculated as a ratio to RMS value
+        // (value of data attribute 'hvRef' is 'rms'), optional otherwise
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO
+//        if( mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional != null ) {
+//            
+//        }
+
+        // presCond: "MOrootLD" :
+        // Element is mandatory in the context of a root logical device; otherwise it is optional
+        // Usage in standard NSD files (version 2007B): DataObject
+//        if( mandatoryInRootLogicalDeviceElseOptional != null ) {
+//
+//        }
+
+        // presCond: "MOoperTm" :
+        // Element is mandatory if at least one controlled object on the IED supports time activation service; otherwise it is optional
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO
+//        if( mandatoryIfControlSupportsTimeElseOptional != null ) {
+//            
+//        }
+
+        // presCond: "MmultiF" :
+        // Parameter sibling: sibling element name.
+        // One or more elements must be present if sibling element is present, otherwise forbidden
+        // Usage in standard NSD files (version 2007B): DataObject
+        // TODO: One or more elements ? Is there an instance number ?
+//        if( oneOrMoreIfSiblingPresentElseForbidden != null ) {
+//            
+//        }
+
+        // presCond: "MOsbo" :
+        // Element is mandatory if declared control model supports 'sbo-with-normal-security' or 'sbo-with-enhanced-security',
+        // otherwise optional and value is of no impact
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO
+//        if( mandatoryIfControlSupportsSecurity1ElseOptional != null ) {
+//            
+//        }
+
+        // presCond: "MOenhanced" :
+        // Element is mandatory if declared control model supports 'direct-with-enhanced-security' or 'sbo-with-enhanced-security',
+        // otherwise optional and value is of no impact
+        // Usage in standard NSD files (version 2007B): DataAttribute
+        // TODO
+//        if( mandatoryIfControlSupportsSecurity2ElseOptional != null ) {
+//            
+//        }
+
+        // presCond: "MONamPlt" :
+        // Element is mandatory if the name space of its logical node deviates from the name space of the containing
+        // logical device, otherwise optional. See IEC 61850-7-1 for use of name space
+        // Usage in standard NSD files (version 2007B): DataObject
+        // TODO: same as "MOlnNs" ?
+//        if( mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2 != null ) {
+//            
+//        }
+
+        // presCond: "OF" :
+        // Parameter sibling: sibling element name.
+        // Optional if sibling element is present, otherwise forbidden
+        // Usage in standard NSD files (version 2007B): DataObject and DataAttribute
+        if( optionalIfSiblingPresentElseForbidden != null ) {
+            for( Entry< String, String > entry : optionalIfSiblingPresentElseForbidden.entrySet() ) {
+                if( presentDA.get( entry.getValue() ) == null ) {
+                    if( presentDA.get( entry.getKey() ) != null ) {
+                        diagnostics.add( new BasicDiagnostic(
+                                Diagnostic.ERROR,
+                                RiseClipseValidatorSCL.DIAGNOSTIC_SOURCE,
+                                0,
+                                "[NSD validation] DA " + entry.getKey() + " is forbidden in DOType (line " + doType.getLineNumber() + ") with LNClass "
+                                        + cdc.getName() + " because sibling " + entry.getValue() + " is not present",
+                                new Object[] { doType } ));
+                        res = false;
+                    }
+                }
+            }
+        }
+
+        // presCond: "MORange" :
+        // Element is mandatory if the measured value associated (amplitude respectively angle) exposes the range eventing
+        // (with the attribute range respectively rangeAng)
+        // Usage in standard NSD files (version 2007B): SubDataAttribute
+        // TODO
+//        if( mandatoryIfMeasuredValueExposesRange != null ) {
+//            
+//        }
+
+        // presCond: "OMSynPh" :
+        // This attribute is optional if value of 'phsRef'' is Synchrophasor otherwise Mandatory]]></Doc>
+        // Usage in standard NSD files (version 2007B): SubDataObject
+        // TODO
+//        if( optionalIfPhsRefIsSynchrophasorElseMandatory != null ) {
+//            
+//        }
+
+        return res;
+    }
+
+}
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/PresenceConditionValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataObjectPresenceConditionValidator.java
similarity index 95%
rename from fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/PresenceConditionValidator.java
rename to fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataObjectPresenceConditionValidator.java
index de3747cac2df76ef1a1491098e0825fb5a01e993..40962fabab08674f1eaaa803a6ac23f2e7c2e150 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/PresenceConditionValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/DataObjectPresenceConditionValidator.java
@@ -1,3 +1,21 @@
+/**
+ *  Copyright (c) 2019 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
 package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.nsd;
 
 import java.util.HashMap;
@@ -11,7 +29,6 @@ import org.eclipse.emf.common.util.Diagnostic;
 import org.eclipse.emf.common.util.DiagnosticChain;
 
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.AnyLNClass;
-import fr.centralesupelec.edf.riseclipse.iec61850.nsd.DataObject;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.AnyLN;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.DA;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.DO;
@@ -23,19 +40,19 @@ import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.RiseClipseValida
 import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
 import fr.centralesupelec.edf.riseclipse.util.IRiseClipseConsole;
 
-public class PresenceConditionValidator {
+public class DataObjectPresenceConditionValidator {
     
-    private static HashMap< String, PresenceConditionValidator > validators = new HashMap<>();
+    private static HashMap< String, DataObjectPresenceConditionValidator > validators = new HashMap<>();
     
-    public static PresenceConditionValidator get( AnyLNClass anyLNClass ) {
+    public static DataObjectPresenceConditionValidator get( AnyLNClass anyLNClass ) {
         if( ! validators.containsKey( anyLNClass.getName() )) {
-            validators.put( anyLNClass.getName(), new PresenceConditionValidator( anyLNClass ));
+            validators.put( anyLNClass.getName(), new DataObjectPresenceConditionValidator( anyLNClass ));
         }
         return validators.get( anyLNClass.getName() );
     }
     
     private AnyLNClass anyLNClass;
-    private PresenceConditionValidator base;
+    private DataObjectPresenceConditionValidator base;
     
     private static class SingleOrMultiDO {
     }
@@ -99,12 +116,14 @@ public class PresenceConditionValidator {
     
     private final IRiseClipseConsole console = AbstractRiseClipseConsole.getConsole();
     
-    private PresenceConditionValidator( AnyLNClass anyLNClass ) {
+    private DataObjectPresenceConditionValidator( AnyLNClass anyLNClass ) {
         this.anyLNClass = anyLNClass;
         
-        for( DataObject dObj : anyLNClass.getDataObject() ) {
-            addSpecification( dObj.getName(), dObj.getPresCond(), dObj.getPresCondArgs() );
-        }
+        anyLNClass
+        .getDataObject()
+        .stream()
+        .forEach( d -> addSpecification( d.getName(), d.getPresCond(), d.getPresCondArgs() ) );
+        
         checkSpecification();
         
         AnyLNClass parent = anyLNClass.getRefersToAbstractLNClass();
@@ -123,7 +142,7 @@ public class PresenceConditionValidator {
     
     private void addSpecification( String name, String presCond, String presCondArgs ) {
         if( presentDO.containsKey( name )) {
-            console.warning( "[NSD setup] " + name + " has already been added to PresenceConditionValidator" );
+            console.warning( "[NSD setup] " + name + " has already been added to DataObjectPresenceConditionValidator" );
             return;
         }
         presentDO.put( name, null );
@@ -147,7 +166,7 @@ public class PresenceConditionValidator {
         case "na" :
             // Element is not applicable
             // -> TODO: what does it mean ? what do we have to check ?
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"na\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"na\" in PresenceCondition" );
 //            if( notApplicable == null ) notApplicable = new HashSet<>();
 //            notApplicable.add( name );
             break;
@@ -373,7 +392,7 @@ public class PresenceConditionValidator {
         case "MFsubst" :
             // Element is mandatory if substitution is supported (for substitution, see IEC 61850-7-3), otherwise forbidden
             // TODO: how do we know if substitution is supported ?
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MFsubst\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MFsubst\" in PresenceCondition" );
 //            if( mandatoryIfSubstitutionElseForbidden == null ) mandatoryIfSubstitutionElseForbidden = new HashSet<>();
 //            mandatoryIfSubstitutionElseForbidden.add( name );
             break;
@@ -390,14 +409,14 @@ public class PresenceConditionValidator {
         case "MOlnNs" :
             // Element is mandatory if the name space of its logical node deviates from the name space of the containing
             // logical device, otherwise optional. See IEC 61850-7-1 for use of name space
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MOlnNs\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOlnNs\" in PresenceCondition" );
 //            if( mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional == null ) mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional = new HashSet<>();
 //            mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional.add( name );
             break;
         case "MOdataNs" :
             // Element is mandatory if the name space of its data object deviates from the name space of its logical node,
             // otherwise optional. See IEC 61850-7-1 for use of name space
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MOdataNs\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOdataNs\" in PresenceCondition" );
 //            if( mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional == null ) mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional = new HashSet<>();
 //            mandatoryIfNameSpaceOfDataObjectDeviatesElseOptional.add( name );
             break;
@@ -405,28 +424,28 @@ public class PresenceConditionValidator {
             // Element is mandatory* if any sibling elements of type AnalogueValue include 'i' as a child, otherwise forbidden.
             // *Even though devices without floating point capability cannot exchange floating point values through ACSI services,
             // the description of scaling remains mandatory for their (SCL) configuration
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MFscaledAV\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MFscaledAV\" in PresenceCondition" );
 //            if( mandatoryIfAnalogValueIncludesIElseForbidden == null ) mandatoryIfAnalogValueIncludesIElseForbidden = new HashSet<>();
 //            mandatoryIfAnalogValueIncludesIElseForbidden.add( name );
             break;
         case "MFscaledMagV" :
             // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'mag' attribute, otherwise forbidden.
             // *See MFscaledAV
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MFscaledMagV\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MFscaledMagV\" in PresenceCondition" );
 //            if( mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden == null ) mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden = new HashSet<>();
 //            mandatoryIfVectorSiblingIncludesIAsChildMagElseForbidden.add( name );
             break;
         case "MFscaledAngV" :
             // Element is mandatory* if any sibling elements of type Vector include 'i' as a child of their 'ang' attribute, otherwise forbidden.
             // *See MFscaledAV
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MFscaledAngV\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MFscaledAngV\" in PresenceCondition" );
 //            if( mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden == null ) mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden = new HashSet<>();
 //            mandatoryIfVectorSiblingIncludesIAsChildAngElseForbidden.add( name );
             break;
         case "MOrms" :
             // Element is mandatory if the harmonic values in the context are calculated as a ratio to RMS value
             // (value of data attribute 'hvRef' is 'rms'), optional otherwise
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MOrms\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOrms\" in PresenceCondition" );
 //            if( mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional == null ) mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional = new HashSet<>();
 //            mandatoryIfHarmonicValuesCalculatedAsRatioElseOptional.add( name );
             break;
@@ -437,28 +456,28 @@ public class PresenceConditionValidator {
             break;
         case "MOoperTm" :
             // Element is mandatory if at least one controlled object on the IED supports time activation service; otherwise it is optional
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MOoperTm\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOoperTm\" in PresenceCondition" );
 //            if( mandatoryIfControlSupportsTimeElseOptional == null ) mandatoryIfControlSupportsTimeElseOptional = new HashSet<>();
 //            mandatoryIfControlSupportsTimeElseOptional.add( name );
             break;
         case "MmultiF" :
             // Parameter sibling: sibling element name.
             // One or more elements must be present if sibling element is present, otherwise forbidden
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MmultiF\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MmultiF\" in PresenceCondition" );
 //            if( oneOrMoreIfSiblingPresentElseForbidden == null ) oneOrMoreIfSiblingPresentElseForbidden = new HashMap<>();
 //            oneOrMoreIfSiblingPresentElseForbidden.put( name, presCondArgs );
             break;
         case "MOsbo" :
             // Element is mandatory if declared control model supports 'sbo-with-normal-security' or 'sbo-with-enhanced-security',
             // otherwise optional and value is of no impact
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MOsbo\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOsbo\" in PresenceCondition" );
 //            if( mandatoryIfControlSupportsSecurity1ElseOptional == null ) mandatoryIfControlSupportsSecurity1ElseOptional = new HashSet<>();
 //            mandatoryIfControlSupportsSecurity1ElseOptional.add( name );
             break;
         case "MOenhanced" :
             // Element is mandatory if declared control model supports 'direct-with-enhanced-security' or 'sbo-with-enhanced-security',
             // otherwise optional and value is of no impact
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MOenhanced\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MOenhanced\" in PresenceCondition" );
 //            if( mandatoryIfControlSupportsSecurity2ElseOptional == null ) mandatoryIfControlSupportsSecurity2ElseOptional = new HashSet<>();
 //            mandatoryIfControlSupportsSecurity2ElseOptional.add( name );
             break;
@@ -466,7 +485,7 @@ public class PresenceConditionValidator {
             // Element is mandatory if the name space of its logical node deviates from the name space of the containing
             // logical device, otherwise optional. See IEC 61850-7-1 for use of name space
             // TODO: same as "MOlnNs" ?
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MONamPlt\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MONamPlt\" in PresenceCondition" );
 //            if( mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2 == null ) mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2 = new HashSet<>();
 //            mandatoryIfNameSpaceOfLogicalNodeDeviatesElseOptional2.add( name );
             break;
@@ -479,13 +498,13 @@ public class PresenceConditionValidator {
         case "MORange" :
             // Element is mandatory if the measured value associated (amplitude respectively angle) exposes the range eventing
             // (with the attribute range respectively rangeAng)
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"MORange\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"MORange\" in PresenceCondition" );
 //            if( mandatoryIfMeasuredValueExposesRange == null ) mandatoryIfMeasuredValueExposesRange = new HashSet<>();
 //            mandatoryIfMeasuredValueExposesRange.add( name );
             break;
         case "OMSynPh" :
             // This attribute is optional if value of 'phsRef'' is Synchrophasor otherwise Mandatory]]></Doc>
-            console.warning( "[NSD setup] NOT IMPLEMENTED: " + name + " declared as \"OMSynPh\" in PresenceCondition" );
+            console.warning( "[NSD setup] NOT IMPLEMENTED: DataObject " + name + " declared as \"OMSynPh\" in PresenceCondition" );
 //            if( optionalIfPhsRefIsSynchrophasorElseMandatory == null ) optionalIfPhsRefIsSynchrophasorElseMandatory = new HashSet<>();
 //            optionalIfPhsRefIsSynchrophasorElseMandatory.add( name );
             break;
@@ -698,7 +717,7 @@ public class PresenceConditionValidator {
                             "[NSD validation] DO " + name + " should not have an instance number in LNodeType (line " + lNodeType.getLineNumber() + ") with LNClass " + anyLNClassName,
                             new Object[] { lNodeType } ));
                     res = false;
-                  }
+                }
             }
         }
 
@@ -724,7 +743,7 @@ public class PresenceConditionValidator {
                             "[NSD validation] DO " + name + " should not have an instance number in LNodeType (line " + lNodeType.getLineNumber() + ") with LNClass " + anyLNClassName,
                             new Object[] { lNodeType } ));
                     res = false;
-                  }
+                }
             }
         }
 
@@ -1051,7 +1070,7 @@ public class PresenceConditionValidator {
                         .map( p -> p.getMixed() )
                         .map( p -> p.get( 0 ) )
                         .map( p -> p.getValue() )
-                        .map(  p -> p.toString() )
+                        .map( p -> p.toString() )
                         .orElse( null );
 
                 diagnostics.add( new BasicDiagnostic(
@@ -1081,7 +1100,7 @@ public class PresenceConditionValidator {
                         .map( p -> p.getMixed() )
                         .map( p -> p.get( 0 ) )
                         .map( p -> p.getValue() )
-                        .map(  p -> p.toString() )
+                        .map( p -> p.toString() )
                         .orElse( null );
 
                 diagnostics.add( new BasicDiagnostic(
@@ -1111,7 +1130,7 @@ public class PresenceConditionValidator {
                         .map( p -> p.getMixed() )
                         .map( p -> p.get( 0 ) )
                         .map( p -> p.getValue() )
-                        .map(  p -> p.toString() )
+                        .map( p -> p.toString() )
                         .orElse( null );
 
                 diagnostics.add( new BasicDiagnostic(
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/LNodeTypeValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/LNodeTypeValidator.java
index a585eece7595e2766b829ffb8a99bf06f78180b8..03c08ec71fda62b041a3f0553a24b7a637c1a5ef 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/LNodeTypeValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/LNodeTypeValidator.java
@@ -18,29 +18,84 @@
  */
 package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.nsd;
 
+import java.util.HashMap;
+
 import org.eclipse.emf.common.util.DiagnosticChain;
 
 import fr.centralesupelec.edf.riseclipse.iec61850.nsd.AnyLNClass;
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.CDC;
+import fr.centralesupelec.edf.riseclipse.iec61850.nsd.DataObject;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.DO;
+import fr.centralesupelec.edf.riseclipse.iec61850.scl.DOType;
 import fr.centralesupelec.edf.riseclipse.iec61850.scl.LNodeType;
 import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
 
 public class LNodeTypeValidator {
 
-    private PresenceConditionValidator presenceConditionValidator;
+    private DataObjectPresenceConditionValidator dataObjectPresenceConditionValidator;
+    private HashMap< String, DOTypeValidator > doTypeValidatorMap = new HashMap<>();
 
-    public LNodeTypeValidator( AnyLNClass lnClass ) {
-        presenceConditionValidator = PresenceConditionValidator.get( lnClass );
-    }
+    public LNodeTypeValidator( AnyLNClass anyLNClass ) {
+        dataObjectPresenceConditionValidator = DataObjectPresenceConditionValidator.get( anyLNClass );
+        
+        AnyLNClass lnClass = anyLNClass;
+        while( lnClass != null ) {
+            for( DataObject do_ : lnClass.getDataObject() ) {
+                CDC cdc = do_.getRefersToCDC();
+                if( cdc != null ) {
+                    doTypeValidatorMap.put( do_.getName(), new DOTypeValidator( cdc ));
+                }
+                else {
+                    AbstractRiseClipseConsole.getConsole().warning( "[NSD setup] CDC for DataObject " + do_.getName() + " not found" );
+                }
+            }
 
+            lnClass = lnClass.getRefersToAbstractLNClass();
+        }
+    }
+    
     public boolean validateLNodeType( LNodeType lNodeType, DiagnosticChain diagnostics ) {
         AbstractRiseClipseConsole.getConsole().verbose( "[NSD] validateLNodeType( " + lNodeType.getId() + " )" );
-        presenceConditionValidator.reset();
+        boolean res = true;
+        dataObjectPresenceConditionValidator.reset();
+        
+        lNodeType
+        .getDO()
+        .stream()
+        .forEach( d -> dataObjectPresenceConditionValidator.addDO( d, diagnostics ));
+      
+        res = res && dataObjectPresenceConditionValidator.validate( lNodeType, diagnostics );
+        
         for( DO do_ : lNodeType.getDO() ) {
-            presenceConditionValidator.addDO( do_, diagnostics );
+            DOType doType = do_.getRefersToDOType();
+            if( doType != null ) {
+                String[] names;
+                if( do_.getName().matches( "[a-zA-Z]+\\d+" )) {
+                    names = do_.getName().split( "(?=\\d)", 2 );
+                }
+                else {
+                    names = new String[] { do_.getName() };
+                }
+                if( names.length == 0 ) {
+                    // error should have been already displayed
+                    //AbstractRiseClipseConsole.getConsole().error( "[NSD validation] Unexpected DO name " + do_.getName() + " in LNodeType (line " + do_.getParentLNodeType().getLineNumber() );
+                    continue;
+                }
+                DOTypeValidator validator = doTypeValidatorMap.get( names[0] );
+                if( validator != null ) {
+                    res = res && validator.validateDOType( doType, diagnostics );
+                }
+                else {
+                    // This error will be detected in DataObjectPresenceConditionValidator.addDO() who will check if it is right if dataNs attribute is present
+                    //AbstractRiseClipseConsole.getConsole().warning( "[NSD validation] while validating LNodeType (line " + lNodeType.getLineNumber() + "): validator for DO " + do_.getName() + " not found" );
+                }
+            }
+            else {
+                AbstractRiseClipseConsole.getConsole().warning( "[NSD validation] DOType for DO " + do_.getName() + " not found" );
+            }
         }
-      
-        return presenceConditionValidator.validate( lNodeType, diagnostics );
+        
+        return res;
     }
 
 }
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/NsdEObjectValidator.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/NsdEObjectValidator.java
index 27cb56515923019f9ddf5d5f595698189e5a044d..31fb0dba5c48970edfc0a9afa0718708e5baa5e9 100644
--- a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/NsdEObjectValidator.java
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/nsd/NsdEObjectValidator.java
@@ -43,7 +43,7 @@ public class NsdEObjectValidator implements EValidator {
 
     private NsdResourceSetImpl nsdResourceSet;
     private HashMap< String, AnyLNValidator > anyLNValidatorMap = new HashMap<>();
-    private HashMap<String,LNodeTypeValidator> lNodeTypeValidatorMap = new HashMap<>();
+    private HashMap< String, LNodeTypeValidator > lNodeTypeValidatorMap = new HashMap<>();
 
     public NsdEObjectValidator( NsdResourceSetImpl nsdResourceSet ) {
         this.nsdResourceSet = nsdResourceSet;