I'm trying to write an Xpath Statement (1.0) that can read info from a 'search' node and perform a search using it.
I was making some nice progress, but stumbled across an issue where if an attribute (used for a value in the search) is empty or doesn't exist, it fails.
Code Edited to simplify Example:
So Here is my sample XML:
<xml>
<files>
<file name="foo" description="" rating="4"/>
<file name="food" description="" rating="4"/>
<file name="foobar" description="" rating="3"/>
<file name="bar" description="" rating="3"/>
<file name="barter" description="" rating="3"/>
<file name="barterer" description="" rating="2"/>
</files>
<searches>
<search id="1">
<exclude>
<file term="foo"/>
</exclude>
</search>
</searches>
</xml>
And working XPATH:
//files/file[
not(contains(@name, //search[@id='1']/exclude/file/@term))
]
It works as expected...
However if the an expected attribute is missing or empty it will fail to work. I think because: contains(@attrib, "") matches everything for some-reason, therefore a not() will always match nothing if the attribute is "" or not present.
For Example, if I alter the exclude fragment of XML to this it fails:
<exclude>
<file term=""/>
</exclude>
with this too:
<exclude></exclude>
Is there a way to Check for an empty value and not perform the select? or is there perhaps a better way of structuring the Logic. Bare in mind I cannot use Conditionals or the other functions in Xpath2.0.
XPath (XML Path Language) is an expression language designed to support the query or transformation of XML documents. It was defined by the World Wide Web Consortium (W3C) and can be used to compute values (e.g., strings, numbers, or Boolean values) from the content of an XML document.
Why does the Xpath function contains() return everything if it search param is blank or missing?
Because that is what the XPath specification says the contains() function should do:
If the value of $arg2 is the zero-length string, then the function returns true.
You could adjust your XPath and simplify some of the conditions with the following:
//files/file[
(
(
not(//search[@id='1']/include/file/@term)
or
(
contains(@name, //search[@id='1']/include/file/@term)
or
contains(@description, //search[@id='1']/include/file/@term)
)
)
or
contains(@rating, //search[@id='1']/include/file/@rating)
)
and
(
(
not(//search[@id='1']/exclude/file/@term)
or
(
not(contains(@name, //search[@id='1']/exclude/file/@term))
and
not(contains(@description, //search[@id='1']/exclude/file/@term))
)
)
and
(
not(//search[@id='1']/exclude/file/@rating)
or
not(contains(@rating, //search[@id='1']/exclude/file/@rating))
)
)
]
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