Added SpanWithAttributeQueryWrapper.
diff --git a/src/main/java/de/ids_mannheim/korap/KorapQuery.java b/src/main/java/de/ids_mannheim/korap/KorapQuery.java
index a64ff13..9af942d 100644
--- a/src/main/java/de/ids_mannheim/korap/KorapQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/KorapQuery.java
@@ -1,6 +1,8 @@
 package de.ids_mannheim.korap;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.lucene.util.automaton.RegExp;
 import org.slf4j.Logger;
@@ -23,6 +25,7 @@
 import de.ids_mannheim.korap.query.wrap.SpanSimpleQueryWrapper;
 import de.ids_mannheim.korap.query.wrap.SpanSubspanQueryWrapper;
 import de.ids_mannheim.korap.query.wrap.SpanWildcardQueryWrapper;
+import de.ids_mannheim.korap.query.wrap.SpanWithAttributeQueryWrapper;
 import de.ids_mannheim.korap.query.wrap.SpanWithinQueryWrapper;
 import de.ids_mannheim.korap.response.Notifications;
 import de.ids_mannheim.korap.util.QueryException;
@@ -752,28 +755,28 @@
         // Branch on type
         switch (type) {
         case "korap:term":
-            String match = "match:eq";
-            if (json.has("match"))
-                match = json.get("match").asText();
-            
-            switch (match) {
-
-            case "match:ne":
-                if (DEBUG)
-                    log.trace("Term is negated");
-
-                SpanSegmentQueryWrapper ssqw =
-                    (SpanSegmentQueryWrapper) this._termFromJson(json);
-
-                ssqw.makeNegative();
-
-                return this.seg().without(ssqw);
-
-            case "match:eq":
+//            String match = "match:eq";
+//            if (json.has("match"))
+//                match = json.get("match").asText();
+//            
+//            switch (match) {
+//
+//            case "match:ne":
+//                if (DEBUG)
+//                    log.trace("Term is negated");
+//
+//                SpanSegmentQueryWrapper ssqw =
+//                    (SpanSegmentQueryWrapper) this._termFromJson(json);
+//
+//                ssqw.makeNegative();
+//
+//                return this.seg().without(ssqw);
+//
+//            case "match:eq":
                 return this._termFromJson(json);
-            };
-
-            throw new QueryException(741, "Match relation unknown");
+//            };
+//
+//            throw new QueryException(741, "Match relation unknown");
 
         case "korap:termGroup":
 
@@ -827,12 +830,11 @@
     // Deserialize korap:term
     private SpanQueryWrapper _termFromJson (JsonNode json)
         throws QueryException {
-
+    	
         if (!json.has("key") || json.get("key").asText().length() < 1) {
-            throw new QueryException(
-                740,
-                "Key definition is missing in term or span"
-            );
+			if (!json.has("attr"))
+				throw new QueryException(740,
+						"Key definition is missing in term or span");
         };
 	    
         if (!json.has("@type")) {
@@ -882,12 +884,6 @@
             case "const":
                 layer = "c";
                 break;
-
-                /*
-                  case "cat":
-                  layer = "c";
-                  break;
-                */
             };
 
             if (isCaseInsensitive && isTerm) {
@@ -935,22 +931,103 @@
             };
         };
 
-        if (isTerm)
-            return this.seg(value.toString());
+        if (isTerm){
+
+        	String match = "match:eq";
+			if (json.has("match")) {
+				match = json.get("match").asText();
+			}
+
+			SpanSegmentQueryWrapper ssqw = seg(value.toString());			
+			if (match.equals("match:ne")) {
+				if (DEBUG) log.trace("Term is negated");
+				ssqw.makeNegative();
+				return this.seg().without(ssqw);
+			} 
+			else if (match.equals("match:eq")) {
+				return ssqw;
+			} 
+			else {
+				throw new QueryException(741, "Match relation unknown");
+			}
+        }
 
         if (json.has("attr")) {
-            this.addWarning(
-                768,
-                "Attributes are currently not supported - results may not be correct"
-            );
+			JsonNode attrNode = json.get("attr");
+			if (!attrNode.has("@type")) {
+				throw new QueryException(701,
+						"JSON-LD group has no @type attribute");
+			}
 
-            // SpanQueryWrapper attrQueryWrapper =
-            // _attrFromJson(json.get("attr"));
-            // if (attrQueryWrapper != null) {
-            // return seg SpanElementWithAttributeQueryWrapper
-            // }
+			if (value.toString().isEmpty()) {
+				// attribute with arbitraty elements
+
+				this.addWarning(771,
+						"Arbitraty elements with attributes are currently not supported.");
+				return null;
+			}
+
+			SpanQueryWrapper elementWithIdWrapper = tag(value.toString());
+			if (elementWithIdWrapper == null) {
+				return null;
+			}
+
+			if (attrNode.get("@type").asText().equals("korap:term")) {
+				SpanQueryWrapper attrWrapper = _attrFromJson(json.get("attr"));
+				if (attrWrapper != null) {
+					return new SpanWithAttributeQueryWrapper(
+							elementWithIdWrapper, attrWrapper);
+				}
+				else {
+					throw new QueryException(747, "Attribute is null");
+				}
+			} 
+			else if (attrNode.get("@type").asText().equals("korap:termGroup")) {
+				if (!attrNode.has("relation")) {
+					throw new QueryException(743, "Term group expects a relation");
+				}
+
+				if (!attrNode.has("operands")) {
+					throw new QueryException(742, "Term group needs operand list");
+				}
+
+				String relation = attrNode.get("relation").asText();
+				JsonNode operands = attrNode.get("operands");
+
+				SpanQueryWrapper attrWrapper;
+				if ("relation:and".equals(relation)) {
+					List<SpanQueryWrapper> wrapperList = new ArrayList<SpanQueryWrapper>();
+					for (JsonNode operand : operands) {
+						attrWrapper = _termFromJson(operand);
+						if (attrWrapper == null) {
+							throw new QueryException(747, "Attribute is null");
+						}
+						wrapperList.add(attrWrapper);
+					}
+
+					return new SpanWithAttributeQueryWrapper(
+							elementWithIdWrapper, wrapperList);
+				}
+				else if ("relation:or".equals(relation)){
+					SpanAlterQueryWrapper saq = new SpanAlterQueryWrapper(field);
+					for (JsonNode operand : operands) {
+						attrWrapper = _termFromJson(operand);
+						if (attrWrapper == null) {
+							throw new QueryException(747, "Attribute is null");
+						}
+						saq.or(new SpanWithAttributeQueryWrapper(
+								elementWithIdWrapper, attrWrapper));
+					}
+					return saq;
+				}
+				else {
+					throw new QueryException(716, "Unknown relation");
+				}
+			}
+			else {
+	            this.addWarning(715, "Attribute type is not supported");
+	        }
         };
-
         return this.tag(value.toString());
     };
 
@@ -959,39 +1036,24 @@
     private SpanQueryWrapper _attrFromJson (JsonNode attrNode)
         throws QueryException {
 
-        if (!attrNode.has("@type")) {
-            throw new QueryException(
-                701,
-                "JSON-LD group has no @type attribute"
+		if (attrNode.has("key")) {
+			return _termFromJson(attrNode);
+		} 
+		else if (attrNode.has("tokenarity") || attrNode.has("arity")) {
+			this.addWarning(770, "Arity attributes are currently not supported"
+					+ " - results may not be correct"
             );
-        };
-
-        if (attrNode.get("@type").asText().equals("korap:term")) {
-            if (attrNode.has("tokenarity") || attrNode.has("arity")) {
-                this.addWarning(
-                    770,
-                    "Arity attributes are currently not supported" +
-                    " - results may not be correct"
+		} 
+		else if (attrNode.has("root")) {
+			String rootValue = attrNode.get("root").asText();
+			if (rootValue.equals("true") || rootValue.equals("false")) {
+				return new SpanAttributeQueryWrapper(
+						new SpanSimpleQueryWrapper("tokens", "@root",
+								Boolean.valueOf(rootValue))
                 );
-            };
-
-            if (attrNode.has("root")) {
-                String rootValue = attrNode.get("root").asText();
-                if (rootValue.equals("true") || rootValue.equals("false")) {
-                    return new SpanAttributeQueryWrapper(
-                        new SpanSimpleQueryWrapper("tokens", "@root"),
-                        Boolean.valueOf(rootValue)
-                    );
-                }
-                // wrong root value
             }
         }
-        // else if termnode
-        else {
-            this.addWarning(715, "Attribute type is not supported");
-        }
-
-        return null;
+		return null;
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/SpanAttributeQuery.java b/src/main/java/de/ids_mannheim/korap/query/SpanAttributeQuery.java
index 49e3cb6..5f4c262 100644
--- a/src/main/java/de/ids_mannheim/korap/query/SpanAttributeQuery.java
+++ b/src/main/java/de/ids_mannheim/korap/query/SpanAttributeQuery.java
@@ -6,6 +6,7 @@
 import org.apache.lucene.index.AtomicReaderContext;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermContext;
+import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.search.spans.SpanTermQuery;
 import org.apache.lucene.search.spans.Spans;
 import org.apache.lucene.util.Bits;
@@ -95,9 +96,8 @@
     public String toString(String field) {
         StringBuilder sb = new StringBuilder();
         sb.append("spanAttribute(");
+		if (negation) sb.append("!");
         sb.append(firstClause.toString(field));
-        if (negation)
-            sb.append(", not");
         sb.append(")");
         sb.append(ToStringUtils.boost(getBoost()));
         return sb.toString();
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAttributeQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAttributeQueryWrapper.java
index 07ca212..87c9d90 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAttributeQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanAttributeQueryWrapper.java
@@ -6,15 +6,26 @@
 import de.ids_mannheim.korap.query.SpanAttributeQuery;
 import de.ids_mannheim.korap.util.QueryException;
 
+/**
+ * @author margaretha
+ * */
 public class SpanAttributeQueryWrapper extends SpanQueryWrapper {
 
-    boolean isNegation = false;
     private SpanQueryWrapper subquery;
 
-    public SpanAttributeQueryWrapper (SpanQueryWrapper sqw, boolean inclusion) {
+	public SpanAttributeQueryWrapper(SpanQueryWrapper sqw) {
+		if (sqw == null) {
+			isNull = true;
+			return;
+		}
+		if (sqw.isEmpty()) {
+			isEmpty = true;
+			return;
+		}
+
         this.subquery = sqw;
-        if (!inclusion) {
-            this.isNegation = true;
+		if (sqw.isNegative) {
+			this.isNegative = true;
         };
 
         if (sqw.maybeUnsorted())
@@ -22,13 +33,20 @@
     };
 
     @Override
-    public SpanQuery toQuery() throws QueryException {
-
+	public SpanQuery toQuery() throws QueryException {
+    	if (isNull || isEmpty) return null;
+    		
         SpanQuery sq = subquery.retrieveNode(this.retrieveNode).toQuery();
+		if (sq == null) {
+			isNull = true;
+			return null;
+		}
+		
         if (sq instanceof SpanTermQuery) {
-            return new SpanAttributeQuery((SpanTermQuery) sq, isNegation, true);
+			return new SpanAttributeQuery((SpanTermQuery) sq, isNegative, true);
         }
-
-        return null; // or exception??
+        else {
+        	throw new IllegalArgumentException("The subquery is not a SpanTermQuery.");
+        }		
     }
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSimpleQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSimpleQueryWrapper.java
index 39c1a7d..ad72570 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSimpleQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSimpleQueryWrapper.java
@@ -12,6 +12,11 @@
         this.query = new SpanTermQuery(new Term(field, term));
     };
 
+	public SpanSimpleQueryWrapper(String field, String term, boolean value) {
+		this(field, term);
+		this.isNegative = !value;
+	}
+
     public SpanSimpleQueryWrapper (SpanQuery query) {
         this.isNull = false;
         this.query = query;
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSubspanQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSubspanQueryWrapper.java
index 1b3d160..2126ee0 100644
--- a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSubspanQueryWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanSubspanQueryWrapper.java
@@ -9,9 +9,6 @@
 import de.ids_mannheim.korap.util.QueryException;
 
 /**
- * Automatically handle the length parameter if it is less than 0, then no
- * SpanSubspanQuery is created, but a SpanQuery for the subquery ?
- * 
  * @author margaretha, diewald
  * 
  */
@@ -102,15 +99,10 @@
 
 	@Override
 	public SpanQuery toQuery() throws QueryException {
-
-		if (this.isNull()) {
-			// if (DEBUG) log.warn("Subquery of SpanSubspanquery is null.");
-			return null;
-		}
+		if (this.isNull()) { return null; }
 
 		SpanQuery sq = subquery.retrieveNode(this.retrieveNode).toQuery();
-		if (sq == null)
-			return null;
+		if (sq == null) return null;
 		if (sq instanceof SpanTermQuery) {
 			if (subquery.isNegative()) {
 				return sq;
diff --git a/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java
new file mode 100644
index 0000000..517e4c6
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/wrap/SpanWithAttributeQueryWrapper.java
@@ -0,0 +1,120 @@
+package de.ids_mannheim.korap.query.wrap;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.search.spans.SpanTermQuery;
+
+import de.ids_mannheim.korap.query.SpanAttributeQuery;
+import de.ids_mannheim.korap.query.SpanWithAttributeQuery;
+import de.ids_mannheim.korap.query.SpanWithIdQuery;
+import de.ids_mannheim.korap.util.QueryException;
+
+public class SpanWithAttributeQueryWrapper extends SpanQueryWrapper {
+
+	private SpanQueryWrapper withIdQueryWrapper = null;
+	private SpanQueryWrapper attrQueryWrapper = null;
+	private List<SpanQueryWrapper> queryWrapperList = null;
+
+	public SpanWithAttributeQueryWrapper(SpanQueryWrapper withIdQuery,
+			SpanQueryWrapper attrQuery) {
+
+		if (withIdQuery != null || attrQuery != null) {
+			isNull = false;
+		}
+		if (withIdQuery.isEmpty || attrQuery.isEmpty()) {
+			isEmpty = true;
+			return;
+		}
+
+		this.attrQueryWrapper = attrQuery;
+		this.withIdQueryWrapper = withIdQuery;
+	}
+
+	public SpanWithAttributeQueryWrapper(SpanQueryWrapper withIdQuery,
+			List<SpanQueryWrapper> attrList) {
+
+		if (withIdQuery != null || attrList != null) {
+			isNull = false;
+		}
+		if (withIdQuery.isEmpty) {
+			isEmpty = true;
+			return;
+		}
+
+		for (SpanQueryWrapper sqw : attrList) {
+			if (sqw == null) {
+				isNull = true;
+				return;
+			}
+			if (sqw.isEmpty) {
+				isEmpty = true;
+				return;
+			}
+		}
+		if (attrList.isEmpty()) {
+			// not withattribute query, just a normal query
+		}
+		this.queryWrapperList = attrList;
+		this.withIdQueryWrapper = withIdQuery;
+	}
+
+	public SpanAttributeQuery createSpanAttributeQuery(
+			SpanQueryWrapper attrQueryWrapper) throws QueryException {
+		SpanQuery sq = attrQueryWrapper.toQuery();
+		if (sq == null) {
+			isNull = true;
+			return null;
+		}
+		if (sq instanceof SpanTermQuery) {
+			return new SpanAttributeQuery(
+					(SpanTermQuery) sq,
+					attrQueryWrapper.isNegative, true);
+		} 
+		else {
+			throw new IllegalArgumentException(
+					"The subquery is not a SpanTermQuery.");
+		}
+	}
+
+	@Override
+	public SpanQuery toQuery() throws QueryException {
+
+		if (isNull || isEmpty) return null;
+		
+		SpanWithIdQuery withIdQuery = (SpanWithIdQuery) withIdQueryWrapper
+				.toQuery();
+		if (withIdQuery == null) {
+			isNull = true;
+			return null;
+		}
+		
+		if (attrQueryWrapper != null){
+			SpanAttributeQuery attrQuery = createSpanAttributeQuery(attrQueryWrapper);
+			if (attrQuery == null) {
+				isNull = true;
+				return null;
+			}
+			return new SpanWithAttributeQuery(withIdQuery, attrQuery, true);
+		}
+		else if (queryWrapperList != null) {
+			if (queryWrapperList.isEmpty()) {
+				return withIdQuery;
+			}
+
+			List<SpanQuery> attrQueries = new ArrayList<SpanQuery>();
+			SpanQuery attrQuery;
+			for (SpanQueryWrapper sqw : queryWrapperList) {
+				attrQuery = createSpanAttributeQuery(sqw);
+				if (attrQuery == null) {
+					isNull = true;
+					return null;
+				}
+				attrQueries.add(attrQuery);
+			}
+			return new SpanWithAttributeQuery(withIdQuery, attrQueries, true);
+		}
+		return null;		
+	}
+}
diff --git a/src/test/java/de/ids_mannheim/korap/query/TestSpanWithAttributeJSON.java b/src/test/java/de/ids_mannheim/korap/query/TestSpanWithAttributeJSON.java
new file mode 100644
index 0000000..a04e6f7
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/query/TestSpanWithAttributeJSON.java
@@ -0,0 +1,74 @@
+package de.ids_mannheim.korap.query;
+
+import static de.ids_mannheim.korap.TestSimple.getJSONQuery;
+import static org.junit.Assert.assertEquals;
+
+import org.apache.lucene.search.spans.SpanQuery;
+import org.junit.Test;
+
+import de.ids_mannheim.korap.query.wrap.SpanQueryWrapper;
+import de.ids_mannheim.korap.util.QueryException;
+
+public class TestSpanWithAttributeJSON {
+
+	@Test
+	public void testElementSingleAttribute() throws QueryException {
+		String filepath = getClass().getResource(
+				"/queries/attribute/element-single-attribute.jsonld").getFile();
+		SpanQueryWrapper sqwi = getJSONQuery(filepath);
+		SpanQuery sq = sqwi.toQuery();
+		assertEquals(
+				"spanElementWithAttribute(<tokens:head />, spanAttribute(tokens:type:top))",
+				sq.toString());
+	}
+
+	@Test
+	public void testElementSingleNotAttribute() throws QueryException {
+		String filepath = getClass().getResource(
+				"/queries/attribute/element-single-not-attribute.jsonld")
+				.getFile();
+		SpanQueryWrapper sqwi = getJSONQuery(filepath);
+		SpanQuery sq = sqwi.toQuery();
+		assertEquals(
+				"spanElementWithAttribute(<tokens:head />, spanAttribute(!tokens:type:top))",
+				sq.toString());
+	}
+
+	@Test
+	public void testElementMultipleAndNotAttributes() throws QueryException {
+		String filepath = getClass().getResource(
+						"/queries/attribute/element-multiple-and-not-attributes.jsonld")
+				.getFile();
+		SpanQueryWrapper sqwi = getJSONQuery(filepath);
+		SpanQuery sq = sqwi.toQuery();
+		assertEquals(
+				"spanElementWithAttribute(<tokens:div />, [spanAttribute(tokens:type:Zeitschrift), "
+						+ "spanAttribute(!tokens:complete:Y), spanAttribute(tokens:n:0)])",
+				sq.toString());
+	}
+
+	@Test
+	public void testElementMultipleOrAttributes() throws QueryException {
+		String filepath = getClass().getResource(
+				"/queries/attribute/element-multiple-or-attributes.jsonld")
+				.getFile();
+		SpanQueryWrapper sqwi = getJSONQuery(filepath);
+		SpanQuery sq = sqwi.toQuery();
+		assertEquals(
+				"spanOr([spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:type:Zeitschrift)), "
+						+ "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:complete:Y)), "
+						+ "spanElementWithAttribute(<tokens:div />, spanAttribute(tokens:n:0))])",
+				sq.toString());
+	}
+
+	@Test
+	public void testAnyElementWithAttribute() throws QueryException {
+		String filepath = getClass().getResource(
+				"/queries/attribute/any-element-with-attribute.jsonld")
+				.getFile();
+		SpanQueryWrapper sqwi = getJSONQuery(filepath);
+		// SpanQuery sq = sqwi.toQuery();
+		assertEquals(null, sqwi);
+	}
+
+}
diff --git a/src/test/resources/queries/attribute/any-element-with-attribute.jsonld b/src/test/resources/queries/attribute/any-element-with-attribute.jsonld
new file mode 100644
index 0000000..25b39b4
--- /dev/null
+++ b/src/test/resources/queries/attribute/any-element-with-attribute.jsonld
@@ -0,0 +1,19 @@
+{
+    "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld",
+    "errors": [],
+    "warnings": [],
+    "messages": [],
+    "collection": {},
+    "query": {
+        "@type": "korap:span",
+        "attr": {
+            "@type": "korap:term",
+            "arity": {
+                "@type": "korap:boundary",
+                "min": 2,
+                "max": 2
+            }
+        }
+    },
+    "meta": {}
+}
\ No newline at end of file
diff --git a/src/test/resources/queries/attribute/element-multiple-and-not-attributes.jsonld b/src/test/resources/queries/attribute/element-multiple-and-not-attributes.jsonld
new file mode 100644
index 0000000..cd18b96
--- /dev/null
+++ b/src/test/resources/queries/attribute/element-multiple-and-not-attributes.jsonld
@@ -0,0 +1,36 @@
+{
+    "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld",
+    "errors": [],
+    "warnings": [],
+    "messages": [],
+    "collection": {},
+    "query": {
+        "@type": "korap:span",
+        "key": "div",
+        "attr": {
+            "@type": "korap:termGroup",
+            "relation": "relation:and",
+            "operands": [
+                {
+                    "@type": "korap:term",
+                    "layer": "type",
+                    "key": "Zeitschrift",
+                    "match": "match:eq"
+                },
+                {
+                    "@type": "korap:term",
+                    "layer": "complete",
+                    "key": "Y",
+                    "match": "match:ne"
+                },
+                {
+                    "@type": "korap:term",
+                    "layer": "n",
+                    "key": "0",
+                    "match": "match:eq"
+                }
+            ]
+        }
+    },
+    "meta": {}
+}
diff --git a/src/test/resources/queries/attribute/element-multiple-or-attributes.jsonld b/src/test/resources/queries/attribute/element-multiple-or-attributes.jsonld
new file mode 100644
index 0000000..c194f21
--- /dev/null
+++ b/src/test/resources/queries/attribute/element-multiple-or-attributes.jsonld
@@ -0,0 +1,36 @@
+{
+    "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld",
+    "errors": [],
+    "warnings": [],
+    "messages": [],
+    "collection": {},
+    "query": {
+        "@type": "korap:span",
+        "key": "div",
+        "attr": {
+            "@type": "korap:termGroup",
+            "relation": "relation:or",
+            "operands": [
+                {
+                    "@type": "korap:term",
+                    "layer": "type",
+                    "key": "Zeitschrift",
+                    "match": "match:eq"
+                },
+                {
+                    "@type": "korap:term",
+                    "layer": "complete",
+                    "key": "Y",
+                    "match": "match:eq"
+                },
+                {
+                    "@type": "korap:term",
+                    "layer": "n",
+                    "key": "0",
+                    "match": "match:eq"
+                }
+            ]
+        }
+    },
+    "meta": {}
+}
diff --git a/src/test/resources/queries/attribute/element-single-attribute.jsonld b/src/test/resources/queries/attribute/element-single-attribute.jsonld
new file mode 100644
index 0000000..9f21989
--- /dev/null
+++ b/src/test/resources/queries/attribute/element-single-attribute.jsonld
@@ -0,0 +1,18 @@
+{
+    "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld",
+    "errors": [],
+    "warnings": [],
+    "messages": [],
+    "collection": {},
+    "query": {
+        "@type": "korap:span",
+        "key": "head",
+        "attr": {
+            "@type": "korap:term",
+            "layer": "type",
+            "key": "top",
+            "match": "match:eq"
+        }
+    },
+    "meta": {}
+}
\ No newline at end of file
diff --git a/src/test/resources/queries/attribute/element-single-not-attribute.jsonld b/src/test/resources/queries/attribute/element-single-not-attribute.jsonld
new file mode 100644
index 0000000..c4e8714
--- /dev/null
+++ b/src/test/resources/queries/attribute/element-single-not-attribute.jsonld
@@ -0,0 +1,18 @@
+{
+    "@context": "http://ids-mannheim.de/ns/KorAP/json-ld/v0.2/context.jsonld",
+    "errors": [],
+    "warnings": [],
+    "messages": [],
+    "collection": {},
+    "query": {
+        "@type": "korap:span",
+        "key": "head",
+        "attr": {
+            "@type": "korap:term",
+            "layer": "type",
+            "key": "top",
+            "match": "match:ne"
+        }
+    },
+    "meta": {}
+}
\ No newline at end of file