As pointed out by @wst, cts:not-query matches both documents. cts:* queries correspond to document fragments, not subtrees. You can match the opposite to your conditions by inserting the cts:element-attribute-value-query constructors inside cts:element-query . This will match sample2.xml :
cts:search(/root, cts:element-query(xs:QName("subject"), cts:and-query(( cts:element-attribute-value-query(xs:QName("subject"),xs:QName("id"),"001"), cts:element-attribute-value-query(xs:QName("subject"),xs:QName("role"),"cross")))))
Perhaps you can customize your query requirements to be enough. If not, you can exclude documents matching this search using the except statement. This will match sample1.xml :
cts:search(/root, cts:element-attribute-value-query(xs:QName("subject"),xs:QName("id"),"001")) except cts:search(/root, cts:element-query(xs:QName("subject"), cts:and-query(( cts:element-attribute-value-query(xs:QName("subject"),xs:QName("id"),"001"), cts:element-attribute-value-query(xs:QName("subject"),xs:QName("role"),"cross")))))
If your documents have unique identifiers, you can add range indices and use one of the cts:*-values functions to get unique identifiers for documents matching the second cts:search , and then use cts:not-query and cts:*-range-query to exclude documents from the first cts:search .
source share