<newproducts>
<number id ="1">
<number id ="2">
<number id ="3">
<number id ="4">
<number id ="5">
</newproducts>
<products>
<number>2</number>
<number>3</number>
<number>4</number>
</products>
number id contains 2, 3, 4 so the output should be like this
<number>1</number>
<number>5</number>
because 1 and 5 are not in number id so I want to output them
Why does this not work?
for $z in /newproducts/number[@id/string() != /products/number/text()]
return
<number>{$z}</number>
Is this possible with the contains function or exists or even a if then else ?
The != operator is effectively "is there at least one item in the sequence that is different." If you need to effectively check "are there no items in the sequence that are the same" then use:
not(@id/string = /products/number/text())
instead of
@id/string() != /products/number/text()
Try reworking as follows (I wrapped your input with a root node and corrected some typos along the way here):
let $list :=
<list>
<newproducts>
<number id ="1"/>
<number id ="2"/>
<number id ="3"/>
<number id ="4"/>
<number id ="5"/>
</newproducts>
<products>
<number>2</number>
<number>3</number>
<number>4</number>
</products>
</list>
return
for $z in $list/newproducts/number[not(@id/string() = $list/products/number/text())]
return <number>{$z}</number>
That returns:
<number>
<number id="1"/>
</number>
<number>
<number id="5"/>
</number>
But your expected output doesn't have number enclosed in number, so change your return clause from
<number>{$z}</number>
to something like:
<number>{$z/@id/string()}</number>
for example:
...
for $z in $list/newproducts/number[not(@id/string() = $list/products/number/text())]
return <number>{$z/@id/string()}</number>
which returns
<number>1</number>
<number>5</number>