Incorrect Finnish translation for note warning
Feedback from one of our clients:

> In frameworks\dita\DITA-OT2.x\xsl\common\strings-fi-fi.xml, I would replace
><str name="Warning">Huomautus</str> -> <str name="Warning">Varoitus</str>
>Currently, note and warning have the same title, and this is definitely incorrect in finnish. Actually, it is against the Machinery Directive. 
diff --git a/src/main/java/org/dita/dost/reader/CopyToReader.java b/src/main/java/org/dita/dost/reader/CopyToReader.java
index 717a026f8..c23105338 100644
--- a/src/main/java/org/dita/dost/reader/CopyToReader.java
+++ b/src/main/java/org/dita/dost/reader/CopyToReader.java
@@ -8,6 +8,7 @@
 package org.dita.dost.reader;
 
 import org.dita.dost.log.MessageUtils;
+import org.dita.dost.util.DitaClass;
 import org.dita.dost.writer.AbstractXMLFilter;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
@@ -30,10 +31,10 @@ import static org.dita.dost.util.URLUtils.*;
  */
 public final class CopyToReader extends AbstractXMLFilter {
 
-    /** Map of copy-to target to souce */
+    /** Map of copy-to target to source */
     private final Map<URI, URI> copyToMap = new HashMap<>(16);
-    /** foreign/unknown nesting level */
-    private int foreignLevel = 0;
+    /** DITA class values for open elements **/
+    private final Deque<DitaClass> classes = new LinkedList<>();
     /** chunk nesting level */
     private int chunkLevel = 0;
     /** Stack for @processing-role value */
@@ -63,7 +64,7 @@ public final class CopyToReader extends AbstractXMLFilter {
      * Reset the internal variables.
      */
     public void reset() {
-        foreignLevel = 0;
+        classes.clear();
         chunkLevel = 0;
         copyToMap.clear();
         processRoleStack.clear();
@@ -86,11 +87,12 @@ public final class CopyToReader extends AbstractXMLFilter {
         processRoleStack.push(processingRole);
 
         final String classValue = atts.getValue(ATTRIBUTE_NAME_CLASS);
-
-        if (foreignLevel > 0) {
-            foreignLevel++;
-        } else if (TOPIC_FOREIGN.matches(classValue) || TOPIC_UNKNOWN.matches(classValue)) {
-            foreignLevel++;
+        
+        final DitaClass cls = atts.getValue(ATTRIBUTE_NAME_CLASS) != null ? new DitaClass(atts.getValue(ATTRIBUTE_NAME_CLASS)) : new DitaClass("");
+        if (cls.isValid()) {
+        	classes.addFirst(cls);
+        }else {
+        	classes.addFirst(null);
         }
 
         if (chunkLevel > 0) {
@@ -109,10 +111,8 @@ public final class CopyToReader extends AbstractXMLFilter {
     @Override
     public void endElement(final String uri, final String localName, final String qName) throws SAXException {
         processRoleStack.pop();
-
-        if (foreignLevel > 0) {
-            foreignLevel--;
-        }
+        classes.pop();
+        
         if (chunkLevel > 0) {
             chunkLevel--;
         }
diff --git a/src/main/java/org/dita/dost/reader/GenListModuleReader.java b/src/main/java/org/dita/dost/reader/GenListModuleReader.java
index 3617fd497..10d65c3cd 100644
--- a/src/main/java/org/dita/dost/reader/GenListModuleReader.java
+++ b/src/main/java/org/dita/dost/reader/GenListModuleReader.java
@@ -12,12 +12,15 @@ import static org.dita.dost.util.Configuration.*;
 import static org.dita.dost.util.Constants.*;
 import static org.dita.dost.util.URLUtils.*;
 import static org.dita.dost.reader.ChunkMapReader.*;
+import static org.dita.dost.util.XMLUtils.nonDitaContext;
 
 import java.net.URI;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.Set;
 import java.util.Stack;
@@ -73,8 +76,8 @@ public final class GenListModuleReader extends AbstractXMLFilter {
     private final Map<URI, URI> copytoMap = new HashMap<>(16);
     /** Flag for conrefpush */
     private boolean hasconaction = false;
-    /** foreign/unknown nesting level */
-    private int foreignLevel = 0;
+    /** DITA class values for open elements **/
+    private final Deque<DitaClass> classes = new LinkedList<>();
     /** Flag used to mark if current file is still valid after filtering */
     private boolean isValidInput = false;
     /** Set of outer dita files */
@@ -343,7 +346,7 @@ public final class GenListModuleReader extends AbstractXMLFilter {
         hasHref = false;
         hasCodeRef = false;
         currentDir = null;
-        foreignLevel = 0;
+        classes.clear();
         isValidInput = false;
         hasconaction = false;
         coderefTargetSet.clear();
@@ -394,44 +397,48 @@ public final class GenListModuleReader extends AbstractXMLFilter {
             }
         }
 
-        final String classValue = atts.getValue(ATTRIBUTE_NAME_CLASS);
-
-        if (foreignLevel > 0) {
-            foreignLevel++;
-        } else if (TOPIC_FOREIGN.matches(classValue) || TOPIC_UNKNOWN.matches(classValue)) {
-            foreignLevel++;
-        }
-
-        if (foreignLevel == 0) {
-            if (classValue == null && !ELEMENT_NAME_DITA.equals(localName)) {
-                logger.info(MessageUtils.getInstance().getMessage("DOTJ030I", localName).setLocation(atts).toString());
-            }
-
-            if (TOPIC_TOPIC.matches(classValue) || MAP_MAP.matches(classValue)) {
-                final String domains = atts.getValue(ATTRIBUTE_NAME_DOMAINS);
-                if (domains == null) {
-                    logger.info(MessageUtils.getInstance().getMessage("DOTJ029I", localName).setLocation(atts).toString());
-                }
-            }
-
-            if ((MAP_MAP.matches(classValue)) || (TOPIC_TITLE.matches(classValue))) {
-                isValidInput = true;
-            }
+        final DitaClass cls = atts.getValue(ATTRIBUTE_NAME_CLASS) != null ? new DitaClass(atts.getValue(ATTRIBUTE_NAME_CLASS)) : new DitaClass("");
+        if (cls.isValid()) {
+			classes.addFirst(cls);
+		} else {
+			classes.addFirst(null);
+		}
+
+        if (!cls.isValid() && !ELEMENT_NAME_DITA.equals(localName)) {
+        	if (nonDitaContext(classes)) {
+        		// Normal case for bad class: in non DITA context, no message
+        	} else if (atts.getValue(ATTRIBUTE_NAME_CLASS) == null) { // Missing @class
+        		logger.info(MessageUtils.getInstance().getMessage("DOTJ030I", localName).setLocation(atts).toString());
+        	} else { // Invalid DITA @class
+        		logger.info(MessageUtils.getInstance().getMessage("DOTJ070I", atts.getValue(ATTRIBUTE_NAME_CLASS), localName).setLocation(atts).toString());
+        	}
+        } else {
 
-            parseConrefAttr(atts);
-            if (PR_D_CODEREF.matches(classValue)) {
-                parseCoderef(atts);
-            } else if (TOPIC_OBJECT.matches(classValue)) {
-                parseObject(atts);
-            } else if (MAP_TOPICREF.matches(classValue)) {
-                parseAttribute(atts, ATTRIBUTE_NAME_HREF);
-                parseAttribute(atts, ATTRIBUTE_NAME_COPY_TO);
-            } else {
-                parseAttribute(atts, ATTRIBUTE_NAME_HREF);
-            }
-            parseConactionAttr(atts);
-            parseConkeyrefAttr(atts);
-            parseKeyrefAttr(atts);
+        	if (TOPIC_TOPIC.matches(cls) || MAP_MAP.matches(cls)) {
+        		final String domains = atts.getValue(ATTRIBUTE_NAME_DOMAINS);
+        		if (domains == null) {
+        			logger.info(MessageUtils.getInstance().getMessage("DOTJ029I", localName).setLocation(atts).toString());
+        		}
+        	}
+
+        	if ((MAP_MAP.matches(cls)) || (TOPIC_TITLE.matches(cls))) {
+        		isValidInput = true;
+        	}
+
+        	parseConrefAttr(atts);
+        	if (PR_D_CODEREF.matches(cls)) {
+        		parseCoderef(atts);
+        	} else if (TOPIC_OBJECT.matches(cls)) {
+        		parseObject(atts);
+        	} else if (MAP_TOPICREF.matches(cls)) {
+        		parseAttribute(atts, ATTRIBUTE_NAME_HREF);
+        		parseAttribute(atts, ATTRIBUTE_NAME_COPY_TO);
+        	} else {
+        		parseAttribute(atts, ATTRIBUTE_NAME_HREF);
+        	}
+        	parseConactionAttr(atts);
+        	parseConkeyrefAttr(atts);
+        	parseKeyrefAttr(atts);
         }
 
         getContentHandler().startElement(uri, localName, qName, atts);
@@ -513,11 +520,7 @@ public final class GenListModuleReader extends AbstractXMLFilter {
     public void endElement(final String uri, final String localName, final String qName) throws SAXException {
         // @processing-role
         processRoleStack.pop();
-
-        if (foreignLevel > 0) {
-            foreignLevel--;
-            assert foreignLevel >= 0;
-        }
+        classes.pop();
 
         getContentHandler().endElement(uri, localName, qName);
     }
diff --git a/src/main/java/org/dita/dost/util/DitaClass.java b/src/main/java/org/dita/dost/util/DitaClass.java
index c1f8aacbd..ea37c434d 100644
--- a/src/main/java/org/dita/dost/util/DitaClass.java
+++ b/src/main/java/org/dita/dost/util/DitaClass.java
@@ -29,6 +29,8 @@ public final class DitaClass {
     // Variables
 
     private static final Pattern WHITESPACE = Pattern.compile("\\s+");
+    private static final Pattern VALID_DITA_CLASS = Pattern.compile("(\\+|-)\\s+(topic|map)/\\S+\\s+" +
+                                                         "([\\S[^/]]+/\\S+\\s+)*");
 
     /** Module/type pair for the most specialized type, with a single preceding and following space character. */
     public final String matcher;
@@ -36,6 +38,8 @@ public final class DitaClass {
     public final String localName;
     /** Normalized specialization hierarchy string. */
     private final String stringValue;
+    /** Does this class value use valid DITA class syntax */
+    private boolean validDitaClass = false;
 
     // Constructors
 
@@ -54,6 +58,7 @@ public final class DitaClass {
             sb.append(s).append(' ');
         }
         stringValue = sb.toString();
+        validDitaClass = VALID_DITA_CLASS.matcher(stringValue).matches();
     }
 
     /**
@@ -173,5 +178,14 @@ public final class DitaClass {
         }
         return false;
     }
+    
+    /**
+     * Test if the current DitaClass is a valid DITA class value
+     * 
+     * @return {@code true} if uses valid DITA class syntax, otherwise {@code false} 
+     */
+    public boolean isValid () {
+    	return validDitaClass;
+    }
 
 }
diff --git a/src/main/java/org/dita/dost/util/XMLUtils.java b/src/main/java/org/dita/dost/util/XMLUtils.java
index 28914a552..5a695e1de 100644
--- a/src/main/java/org/dita/dost/util/XMLUtils.java
+++ b/src/main/java/org/dita/dost/util/XMLUtils.java
@@ -117,6 +117,27 @@ public final class XMLUtils {
         }
         return res;
     }
+    
+    /**
+     * Checks if the closest DITA ancestor <foreign> or <unknown>
+     * 
+     * @param classes stack of class attributes for open elements
+     * @return true if closest DITA ancestor is <foreign> or <unknown>, otherwise false
+     */
+    public static boolean nonDitaContext(final Deque<DitaClass> classes) {
+    	final Iterator<DitaClass> it = classes.iterator();
+    	it.next(); // Skip first, because we're checking if current element is inside non-DITA context
+    	while (it.hasNext()) {
+    		final DitaClass cls = it.next();
+    		if (cls != null && cls.isValid() && 
+    				(TOPIC_FOREIGN.matches(cls) || TOPIC_UNKNOWN.matches(cls))) {
+    			return true;
+    		} else if (cls != null && cls.isValid()) {
+    			return false;
+    		}
+    	}
+    	return false;
+    }
 
     /**
      * Get specific element node from child nodes.
diff --git a/src/main/java/org/dita/dost/writer/DebugFilter.java b/src/main/java/org/dita/dost/writer/DebugFilter.java
index b63e70e9f..048d24df9 100644
--- a/src/main/java/org/dita/dost/writer/DebugFilter.java
+++ b/src/main/java/org/dita/dost/writer/DebugFilter.java
@@ -11,10 +11,13 @@ import static org.dita.dost.util.Constants.*;
 
 import java.io.File;
 import java.net.URI;
+import java.util.Deque;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.Map;
 
 import org.dita.dost.util.XMLUtils;
+import org.dita.dost.util.DitaClass;
 import org.xml.sax.Attributes;
 import org.xml.sax.Locator;
 import org.xml.sax.SAXException;
@@ -35,7 +38,7 @@ public final class DebugFilter extends AbstractXMLFilter {
 
 	private Locator locator;
 	private final Map<String, Integer> counterMap = new HashMap<>();
-	private int foreignLevel;
+	private final Deque<DitaClass> classes = new LinkedList<>();
 
 	// Locator methods
     
@@ -46,21 +49,20 @@ public final class DebugFilter extends AbstractXMLFilter {
     }
 	
 	// SAX methods
+	@Override
+    public void startDocument() throws SAXException {
+        classes.clear();
+        getContentHandler().startDocument();
+    }
 	
 	@Override
 	public void startElement(final String uri, final String localName, final String qName, final Attributes atts)
 			throws SAXException {
-	    if (foreignLevel > 0) {
-            foreignLevel++;
-        } else if (foreignLevel == 0) {
-            final String classValue = atts.getValue(ATTRIBUTE_NAME_CLASS);
-            if (TOPIC_FOREIGN.matches(classValue) || TOPIC_UNKNOWN.matches(classValue)) {
-                foreignLevel = 1;
-            }
-        }
+		final DitaClass cls = atts.getValue(ATTRIBUTE_NAME_CLASS) != null ? new DitaClass(atts.getValue(ATTRIBUTE_NAME_CLASS)) : null;
+        classes.addFirst(cls);
 	    
 		final AttributesImpl res = new AttributesImpl(atts);
-		if (foreignLevel <= 1){
+		if (cls!=null && !ELEMENT_NAME_DITA.equals(localName)) {
     		XMLUtils.addOrSetAttribute(res, ATTRIBUTE_NAME_XTRF, currentFile.toString());
     		
             Integer nextValue;
@@ -86,9 +88,7 @@ public final class DebugFilter extends AbstractXMLFilter {
 	@Override
     public void endElement(final String uri, final String localName, final String qName)
             throws SAXException {
-        if (foreignLevel > 0){
-            foreignLevel--;
-        }
+        classes.pop();
         super.endElement(uri, localName, qName);
 	}
 	
diff --git a/src/main/java/org/dita/dost/writer/DitaWriterFilter.java b/src/main/java/org/dita/dost/writer/DitaWriterFilter.java
index 7bb1ff8b5..f27258cc3 100644
--- a/src/main/java/org/dita/dost/writer/DitaWriterFilter.java
+++ b/src/main/java/org/dita/dost/writer/DitaWriterFilter.java
@@ -12,6 +12,7 @@ import org.dita.dost.log.MessageUtils;
 import org.dita.dost.module.GenMapAndTopicListModule;
 import org.dita.dost.module.GenMapAndTopicListModule.TempFileNameScheme;
 import org.dita.dost.util.Constants;
+import org.dita.dost.util.DitaClass;
 import org.dita.dost.util.Job;
 import org.dita.dost.util.Job.FileInfo;
 import org.dita.dost.util.StringUtils;
@@ -23,12 +24,15 @@ import org.dita.dost.module.DebugAndFilterModule;
 
 import java.io.File;
 import java.net.URI;
+import java.util.Deque;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.Map;
 
 import static org.dita.dost.util.Constants.*;
 import static org.dita.dost.util.FileUtils.*;
 import static org.dita.dost.util.URLUtils.*;
+import static org.dita.dost.util.XMLUtils.nonDitaContext;
 import static org.dita.dost.reader.GenListModuleReader.*;
 
 
@@ -58,8 +62,10 @@ public final class DitaWriterFilter extends AbstractXMLFilter {
     private Map<String, Map<String, String>> defaultValueMap;
     /** Absolute path to current destination file. */
     private File outputFile;
-    /** Foreign/unknown nesting level. */
-    private int foreignLevel;
+    /** DITA class values for open elements **/
+    private final Deque<DitaClass> classes = new LinkedList<>();
+    /** File infos by src. */
+    private Map<URI, FileInfo> fileInfoMap;
 //    /** File infos by src. */
 //    private Map<URI, FileInfo> fileInfoMap;
     private TempFileNameScheme tempFileNameScheme;
@@ -97,14 +103,14 @@ public final class DitaWriterFilter extends AbstractXMLFilter {
     @Override
     public void endElement(final String uri, final String localName, final String qName)
             throws SAXException {
-        if (foreignLevel > 0) {
-            foreignLevel--;
-        }
+    	classes.pop();
         getContentHandler().endElement(uri, localName, qName);
     }
 
     @Override
     public void startDocument() throws SAXException {
+    	classes.clear();
+    	
         // XXX May be require fixup
         final File path2Project = DebugAndFilterModule.getPathtoProject(getRelativePath(toFile(job.getInputFile()), toFile(currentFile)),
                 toFile(currentFile),
@@ -132,18 +138,11 @@ public final class DitaWriterFilter extends AbstractXMLFilter {
     @Override
     public void startElement(final String uri, final String localName, final String qName,
                              final Attributes atts) throws SAXException {
-        if (foreignLevel > 0) {
-            foreignLevel++;
-        } else if (foreignLevel == 0) {
-            final String attrValue = atts.getValue(ATTRIBUTE_NAME_CLASS);
-            if (attrValue == null && !ELEMENT_NAME_DITA.equals(localName)) {
-                logger.info(MessageUtils.getInstance().getMessage("DOTJ030I", localName).toString());
-            }
-            if (attrValue != null &&
-                    (TOPIC_FOREIGN.matches(attrValue) ||
-                            TOPIC_UNKNOWN.matches(attrValue))) {
-                foreignLevel = 1;
-            }
+    	final DitaClass cls = atts.getValue(ATTRIBUTE_NAME_CLASS) != null ? new DitaClass(atts.getValue(ATTRIBUTE_NAME_CLASS)) : new DitaClass("");
+    	if (cls.isValid()) {
+        	classes.addFirst(cls);
+        }else {
+        	classes.addFirst(null);
         }
 
         final AttributesImpl res = new AttributesImpl();
diff --git a/src/main/java/org/dita/dost/writer/ProfilingFilter.java b/src/main/java/org/dita/dost/writer/ProfilingFilter.java
index 4c4befdd4..4b6691d06 100644
--- a/src/main/java/org/dita/dost/writer/ProfilingFilter.java
+++ b/src/main/java/org/dita/dost/writer/ProfilingFilter.java
@@ -8,14 +8,18 @@
 package org.dita.dost.writer;
 
 import static org.dita.dost.util.Constants.*;
+import static org.dita.dost.util.XMLUtils.nonDitaContext;
 
 import org.dita.dost.log.MessageUtils;
+import org.dita.dost.util.DitaClass;
 import org.dita.dost.util.FilterUtils;
 import org.dita.dost.util.StringUtils;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
+import java.util.Deque;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.Map;
 
 /**
@@ -25,8 +29,8 @@ public final class ProfilingFilter extends AbstractXMLFilter {
 
 	/** when exclude is true the tag will be excluded. */
 	private boolean exclude;
-	/** foreign/unknown nesting level */
-	private int foreignLevel;
+	/** DITA class values for open elements **/
+    private final Deque<DitaClass> classes = new LinkedList<>();
 	/** level is used to count the element level in the filtering */
 	private int level;
 	/** Contains the attribution specialization paths for {@code props} attribute */
@@ -68,23 +72,19 @@ public final class ProfilingFilter extends AbstractXMLFilter {
 	@Override
 	public void startElement(final String uri, final String localName, final String qName, final Attributes atts)
 			throws SAXException {
-		if (foreignLevel > 0) {
-			foreignLevel++;
-		} else if (foreignLevel == 0) {
-			final String classAttr = atts.getValue(ATTRIBUTE_NAME_CLASS);
-			if (classAttr == null && !ELEMENT_NAME_DITA.equals(localName)) {
-				logger.info(MessageUtils.getInstance().getMessage("DOTJ030I", localName).toString());
-			}
-			if (classAttr != null && (TOPIC_TOPIC.matches(classAttr) || MAP_MAP.matches(classAttr))) {
-				final String domains = atts.getValue(ATTRIBUTE_NAME_DOMAINS);
-				if (domains == null) {
-					logger.info(MessageUtils.getInstance().getMessage("DOTJ029I", localName).toString());
-				} else {
-					props = StringUtils.getExtProps(domains);
-				}
-			}
-			if (classAttr != null && (TOPIC_FOREIGN.matches(classAttr) || TOPIC_UNKNOWN.matches(classAttr))) {
-				foreignLevel = 1;
+		final DitaClass cls = atts.getValue(ATTRIBUTE_NAME_CLASS) != null ? new DitaClass(atts.getValue(ATTRIBUTE_NAME_CLASS)) : new DitaClass("");
+		if (cls.isValid()) {
+			classes.addFirst(cls);
+		} else {
+			classes.addFirst(null);
+		}
+		
+        if (cls.isValid() && (TOPIC_TOPIC.matches(cls) || MAP_MAP.matches(cls))) {
+			final String domains = atts.getValue(ATTRIBUTE_NAME_DOMAINS);
+			if (domains == null) {
+				logger.info(MessageUtils.getInstance().getMessage("DOTJ029I", localName).toString());
+			} else {
+				props = StringUtils.getExtProps(domains);
 			}
 		}
 
@@ -92,7 +92,7 @@ public final class ProfilingFilter extends AbstractXMLFilter {
 			// If it is the start of a child of an excluded tag, level increase
 			level++;
 		} else { // exclude shows whether it's excluded by filtering
-			if (foreignLevel <= 1 && filterUtils.needExclude(atts, props)) {
+			if (cls.isValid() && filterUtils.needExclude(atts, props)) {
 				exclude = true;
 				level = 0;
 			} else {
@@ -109,9 +109,7 @@ public final class ProfilingFilter extends AbstractXMLFilter {
 	@Override
 	public void endElement(final String uri, final String localName, final String qName)
 			throws SAXException {
-		if (foreignLevel > 0) {
-			foreignLevel--;
-		}
+		classes.pop();
         lastElementExcluded = exclude;
 		if (exclude) {
 			if (level > 0) {
@@ -175,7 +173,7 @@ public final class ProfilingFilter extends AbstractXMLFilter {
 	@Override
 	public void startDocument() throws SAXException {
 		exclude = false;
-		foreignLevel = 0;
+		classes.clear();
 		level = 0;
 		props = null;
         getContentHandler().startDocument();
diff --git a/src/main/resources/messages_template.xml b/src/main/resources/messages_template.xml
index 9cf11738a..00db38263 100644
--- a/src/main/resources/messages_template.xml
+++ b/src/main/resources/messages_template.xml
@@ -132,7 +132,7 @@ See the accompanying LICENSE file for applicable license.
   
   <message id="DOTJ030I" type="INFO">
     <reason>No 'class' attribute for was found for element '&lt;%1&gt;'.</reason>
-    <response>This generally indicates that your DTD or Schema was not developed properly according to the DITA specification.</response>
+    <response>The element will be processed as an unknown or non-DITA element.</response>
   </message> 
   
   <message id="DOTJ031I" type="INFO">
@@ -333,6 +333,11 @@ See the accompanying LICENSE file for applicable license.
     <response></response>
   </message>
 
+  <message id="DOTJ070I" type="INFO">
+    <reason>Invalid 'class' attribute '%1' for was found for element '&lt;%2&gt;'.</reason>
+    <response>The element will be processed as an unknown or non-DITA element.</response>
+  </message>
+
   <!-- End of Java Messages -->
     
   <!-- Start of XSL Messages -->  
diff --git a/src/test/java/org/dita/dost/util/DitaClassTest.java b/src/test/java/org/dita/dost/util/DitaClassTest.java
index b5d0e33ce..caed51a55 100644
--- a/src/test/java/org/dita/dost/util/DitaClassTest.java
+++ b/src/test/java/org/dita/dost/util/DitaClassTest.java
@@ -91,5 +91,18 @@ public class DitaClassTest {
         assertTrue(new DitaClass("- foo/bar baz/qux ").matches(elem));
         assertFalse(new DitaClass("- bar/baz ").matches(elem));
     }
+    
+    @Test
+    public void testValidDitaClass() {
+        assertTrue(new DitaClass("- topic/p ").isValid());
+        assertTrue(new DitaClass("+ topic/p topic-d/domain_element ").isValid());
+        assertTrue(new DitaClass("+ topic/p topic-d/domain_element   ex+d/x ").isValid());
+        assertTrue(new DitaClass("- map/topicref ").isValid());
+        assertTrue(new DitaClass("+ map/topicref map-d/domain_element ").isValid());
+        assertFalse(new DitaClass("").isValid());
+        assertFalse(new DitaClass("invalid syntax").isValid());
+        assertFalse(new DitaClass("- close/but/invalid ").isValid());
+        assertFalse(new DitaClass("- also\\invalid ").isValid());
+    }
 
 }
diff --git a/src/test/java/org/dita/dost/util/XMLUtilsTest.java b/src/test/java/org/dita/dost/util/XMLUtilsTest.java
index 0961a7872..6e383543a 100644
--- a/src/test/java/org/dita/dost/util/XMLUtilsTest.java
+++ b/src/test/java/org/dita/dost/util/XMLUtilsTest.java
@@ -10,6 +10,8 @@ package org.dita.dost.util;
 import static javax.xml.XMLConstants.*;
 import static org.junit.Assert.*;
 
+import java.util.Deque;
+import java.util.LinkedList;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import org.w3c.dom.Element;
@@ -162,5 +164,47 @@ public class XMLUtilsTest {
         result = XMLUtils.escapeXML(input, 0, input.length);
         assertEquals(expected, result);
     }
+    
+    @Test
+    public void testNonDitaContext() {
+    	/* Queue assumes the following values:
+    	 * <topic class="- topic/topic ">...
+    	 *  <body class="- topic/body ">
+    	 *   <foreign class="- topic/foreign ">
+    	 *    <NONDITA class="nondita">
+    	 *      <moreNonDita/>
+    	 *    </NONDITA>
+    	 *    <ditaInForeign class="- topic/xref foreign-d/ditaInForeign ">
+    	 *      <ph class="- topic/ph "/>
+    	 *    <unknown class="- topic/unknown ">
+    	 *     <moreNonDita><more/></moreNonDita>
+    	 *    </unknown></ditaInForeign></foreign></body></topic>
+    	 */
+    	Deque<DitaClass> classes = new LinkedList<>();
+    	classes.addFirst(new DitaClass("- topic/topic "));
+    	assertFalse(XMLUtils.nonDitaContext(classes));
+    	classes.addFirst(new DitaClass("- topic/body "));
+    	assertFalse(XMLUtils.nonDitaContext(classes));
+    	classes.addFirst(new DitaClass("- topic/foreign "));
+    	assertFalse(XMLUtils.nonDitaContext(classes));
+    	classes.addFirst(new DitaClass("nondita"));
+    	assertTrue(XMLUtils.nonDitaContext(classes));
+    	classes.addFirst(new DitaClass(""));
+    	assertTrue(XMLUtils.nonDitaContext(classes));
+    	classes.pop();
+    	classes.pop();
+    	classes.addFirst(new DitaClass("+ topic/xref foreign-d/ditaInForeign "));
+    	assertTrue(XMLUtils.nonDitaContext(classes));
+    	classes.addFirst(new DitaClass("+ topic/ph "));
+    	assertFalse(XMLUtils.nonDitaContext(classes));
+    	classes.pop();
+    	classes.pop();
+    	classes.addFirst(new DitaClass("- topic/unknown "));
+    	assertTrue(XMLUtils.nonDitaContext(classes));
+    	classes.addFirst(null);
+    	assertTrue(XMLUtils.nonDitaContext(classes));
+    	classes.addFirst(null);
+    	assertTrue(XMLUtils.nonDitaContext(classes));
+    }
 
 }
diff --git a/src/test/resources/ProfilingFilterTest/exp/topic.dita b/src/test/resources/ProfilingFilterTest/exp/topic.dita
index 1dc8007a6..f17c6654a 100644
--- a/src/test/resources/ProfilingFilterTest/exp/topic.dita
+++ b/src/test/resources/ProfilingFilterTest/exp/topic.dita
@@ -11,6 +11,8 @@
     <p class="- topic/p " platform="osx">OS X platform</p>
     <p class="- topic/p " platform="windows osx">Windows and OS X platform</p>
     <foreign class="- topic/foreign ">
+      <para platform="windows">non-DITA para, should not filter</para>
+      <para class="notdita" platform="windows">another non-DITA para, should not filter</para>
       <p class="- topic/p " platform="windows">Foreign Windows</p>
     </foreign>
     <p hardware-platform="" class="- topic/p ">Empty hardware-platform</p>
@@ -24,4 +26,4 @@
          platform="osx">
     <title class="- topic/title ">OS X</title>
   </topic>
-</topic>
\ No newline at end of file
+</topic>
diff --git a/src/test/resources/ProfilingFilterTest/exp/topic1.dita b/src/test/resources/ProfilingFilterTest/exp/topic1.dita
index b12ad76d0..088cbe3cb 100644
--- a/src/test/resources/ProfilingFilterTest/exp/topic1.dita
+++ b/src/test/resources/ProfilingFilterTest/exp/topic1.dita
@@ -11,7 +11,9 @@
     <p class="- topic/p " platform="osx">OS X platform</p>
     <p class="- topic/p " platform="windows osx">Windows and OS X platform</p>
     <foreign class="- topic/foreign ">
-      <p platform="windows" class="- topic/p ">Foreign Windows</p>
+      <para platform="windows">non-DITA para, should not filter</para>
+      <para class="notdita" platform="windows">another non-DITA para, should not filter</para>
+      <!--<p platform="windows" class="- topic/p ">Foreign Windows</p>-->
     </foreign>
     <p hardware-platform="" class="- topic/p ">Empty hardware-platform</p>
     <!--p hardware-platform="arm" class="- topic/p ">ARM hardware-platform</p-->
@@ -24,4 +26,4 @@
          platform="osx">
     <title class="- topic/title ">OS X</title>
   </topic>
-</topic>
\ No newline at end of file
+</topic>
diff --git a/src/test/resources/ProfilingFilterTest/src/topic.dita b/src/test/resources/ProfilingFilterTest/src/topic.dita
index 1dc8007a6..f17c6654a 100644
--- a/src/test/resources/ProfilingFilterTest/src/topic.dita
+++ b/src/test/resources/ProfilingFilterTest/src/topic.dita
@@ -11,6 +11,8 @@
     <p class="- topic/p " platform="osx">OS X platform</p>
     <p class="- topic/p " platform="windows osx">Windows and OS X platform</p>
     <foreign class="- topic/foreign ">
+      <para platform="windows">non-DITA para, should not filter</para>
+      <para class="notdita" platform="windows">another non-DITA para, should not filter</para>
       <p class="- topic/p " platform="windows">Foreign Windows</p>
     </foreign>
     <p hardware-platform="" class="- topic/p ">Empty hardware-platform</p>
@@ -24,4 +26,4 @@
          platform="osx">
     <title class="- topic/title ">OS X</title>
   </topic>
-</topic>
\ No newline at end of file
+</topic>
['src/main/java/org/dita/dost/writer/DitaWriterFilter.java', 'src/test/java/org/dita/dost/util/DitaClassTest.java', 'src/test/java/org/dita/dost/util/XMLUtilsTest.java', 'src/main/resources/messages_template.xml', 'src/test/resources/ProfilingFilterTest/exp/topic.dita', 'src/main/java/org/dita/dost/util/XMLUtils.java', 'src/main/java/org/dita/dost/reader/CopyToReader.java', 'src/main/java/org/dita/dost/writer/ProfilingFilter.java', 'src/main/java/org/dita/dost/writer/DebugFilter.java', 'src/test/resources/ProfilingFilterTest/exp/topic1.dita', 'src/test/resources/ProfilingFilterTest/src/topic.dita', 'src/main/java/org/dita/dost/util/DitaClass.java', 'src/main/java/org/dita/dost/reader/GenListModuleReader.java']