I have the following xmls:
sample1.xml
<root>
<subjectInfo>
<subject id="001"/>
<subject id="002" role="cross"/>
</subjectInfo>
</root>
sample2.xml
<root>
<subjectInfo>
<subject id="002"/>
<subject id="001" role="cross"/>
</subjectInfo>
</root>
I am searching for the documents where value of id
attribute of subject
is "001" but role
(if it's there) of the same subject
element is not "cross".So, In my example the result should contain sample1.xml
and not sample2.xml
I thought the following query would do the job:
<code>
cts:search(/root,
cts:near-query((
cts:element-attribute-value-query(xs:QName("subject"),xs:QName("id"),"001"),
cts:not-query(cts:element-attribute-value-query(xs:QName("subject"),xs:QName("role"),"cross"))),0)
)
</code>
But it does not(returns an empty sequence). Please give me one that does.
As @wst said, the cts:not-query
matches both documents. cts:*
queries match document fragments, not subtrees. You can match the opposite of your conditions, by nesting the cts:element-attribute-value-query
constructors inside of a 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 adjust your query requirements so this is sufficient. If not, you can exclude the documents that match this search, using the except
operator. 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 could add range indices and use one of the cts:*-values
functions to get the unique IDs for documents matching the second cts:search
, and then use cts:not-query
and cts:*-range-query
to exclude the documents from the first cts:search
.
I think the problem is that the cts:not-query
is matching on both documents, and therefore excludes them from the result set.
This may not be sufficient, since it's not an index-only query, but you could supplement the cts:search
results by filtering out false positives:
cts:search(/root,
cts:element-attribute-value-query(xs:QName("subject"),
xs:QName("id"), "001"))[subjectInfo/subject[@id='001' and not(@role='cross')]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With