Does xpath query return incorrect values ​​when using larger and smaller?

This query returns values ​​less than 1000. It should only return values ​​between 1000 and 1100. Why is this?

//results/Building[ 1 = 1 and (( Vacancy/sqft > 1000 ) and ( Vacancy/sqft < 1100 ) ) ]

The request will return the following building with vacancies of less than 1000 square feet and more than 1100 square feet:

 <Building> <Vacancy><sqft>900</sqft></Vacancy> <Vacancy><sqft>1000</sqft></Vacancy> <Vacancy><sqft>2000</sqft></Vacancy> <Vacancy><sqft>500</sqft></Vacancy> </Building> 

Why is it included in the results?

Sample data:

 <results> <Building><!--Shouldn't be selected.--></Building> <Building><!--Should be selected--> <Vacancy><sqft>1050</sqft></Vacancy> </Building> <Building><!--Should be selected--> <Vacancy><sqft>1025</sqft></Vacancy> <Vacancy><sqft>1075</sqft></Vacancy> </Building> <Building><!--Shouldn't be selected--> <Vacancy><sqft>10</sqft></Vacancy> <Vacancy><sqft>50</sqft></Vacancy> </Building> <Building><!--Should be selected.--> <Vacancy><sqft>1050</sqft></Vacancy> <Vacancy><sqft>2000</sqft></Vacancy> </Building> <Building><!--Should be selected.--> <Vacancy><sqft>900</sqft></Vacancy> <Vacancy><sqft>1040</sqft></Vacancy> </Building> <Building><!--Shouldn't be selected--> <Vacancy><sqft>10500</sqft></Vacancy> </Building> <Building><!--Shouldn't be selected--> <Vacancy><sqft>900</sqft></Vacancy> <Vacancy><sqft>1000</sqft></Vacancy> <Vacancy><sqft>2000</sqft></Vacancy> <Vacancy><sqft>500</sqft></Vacancy> </Building> </results> 

Thanks.

+4
source share
5 answers

You also need to match buildings with some square meters outside your criteria, but at least one square inch between 1000-1100, like this

  <Building>Should this be selected too? <Vacancy><sqft>1000</sqft></Vacancy> <Vacancy><sqft>1050</sqft></Vacancy> <Vacancy><sqft>2000</sqft></Vacancy> </Building> 

If yes, use an XPath expression

 /results/Building[Vacancy/sqft[. > 1000 and 1100 > . ] or not(Vacancy)] 

It also selects buildings without a <Vacancy> element (on request).

+6
source

The Building sample has a vacancy child with sqft 2000, so Vacancy/sqft > 1000 succeeds. He has a child with a square mark of 1000 (both 900 and 500), so Vacancy/sqft < 1100 succeeds. Thus, xpath selects Building.

Comparison expressions (for example, Vacancy/sqft <= 1000 ) implicitly qualify as " exists " in "there is a Vacancy child that has a sqft child with a value> 1000" because Vacancy/sqft is a collection of nodes , not one node . Moreover, each comparison has its own qualification, so the sqft in Vacancy/sqft > 1000 does not have to be the same sqft as in Vacancy/sqft < 1100 . Note that //results/Buildings is a collection of node; the predicate [...] is applied separately to each element in the set, so there are no problems with qualifiers. Translating the original xpath into English, we get:

Select buildings (in the results) such that 1 = 1, and there is a square vacancy label> 1000, and there is a square vacancy length <1100.

Let's take the English wording of the desired query and make it a little closer to the logic that comes to one of:

Select the buildings (in the results) so that there is a vacancy with a square mark, so that it> 1000, 1100

Select the buildings (in the results) so that there is a vacancy, so that square meters> 1000 and square meters 1100

The first leads to the solution of yasso, the latter to:

//results/Building[ Vacancy[1000 < sqft and sqft < 1100] ]

Original solution

(Note: this answered the original question when it was not clear what the OP wanted. The technique may be useful to others with a similar problem, but with different requirements, so I leave it.)

Try the logical double negation of the condition:

//results/Building[ Vacancy and not (Vacancy/sqft <= 1000 or Vacancy/sqft >= 1100) ]

This predicate includes a test for Vacancy children to filter out cases that are otherwise trivially true, i.e. buildings without vacancies. The English equivalent of this solution:

Select the buildings (in the results) so that there is a vacancy in the building, and this is not the case when there is a square vacancy label <= 1000 or there is a vacant area in square feet> = 1100

Less words:

Select all buildings with vacancies where the vacancy does not have <= 1000 square feet or> = 1100 square feet.

Even fewer words:

Select all buildings with vacancies where all vacancies range from 1,000 to 1,100 square feet.

+8
source
 //results /Building[1 = 1 and (( Vacancy/sqft > 1000 ) and (Vacancy/sqft < 1100 ))] 

This query returns values ​​less than 1000. It should only return values ​​from 1000 to 1100. Why what?

From http://www.w3.org/TR/xpath/#booleans

If one object for comparison is node-set and the other is a number, then the comparison will be true if and only if there is a node in node-set, so that the result is a comparison of the number to be compared and the result of converting the string value from what node to number using the number function is true.

Node Established comparisons exist comparisons . Vacancy/sqft > 1000 means: is there at least one Vacancy/sqft greater than 1000?

If you want to select Building elements that have Vacancy/sqft grand children, and all of them are in the range (1000,1100), this is an XPath expression:

 /results/Building[Vacancy/sqft and not(Vacancy/sqft[1000 >= . or . >= 1100])] 
+3
source

Try changing xpath to this:

 //results/Building[number(Vacancy/sqft) > 1000 and number(Vacancy/sqft) < 1100 ] 

I suspect it is processing your Vacancy/sqft node text, which may cause some weird things ...

I removed 1 = 1 and additional parsers because I did not see the need for them. The main thing is to try the number function.

UPDATE

This is a bit strange, but it captures the ones you want and the one you are not sure if you want ( Should this be selected? ):

 //results/Building[count(Vacancy[sqft > 1000 and sqft < 1100 ]) = count(Vacancy)] 

and if you want to exclude this:

 //results/Building[(count(Vacancy[sqft > 1000 and sqft < 1100 ]) = count(Vacancy)) and count(Vacancy) > 0] 

I also use this site for the text of my xpaths, if there is any fundamental difference between how they do it and how objective-c let me know ...

+1
source

Here are two XPath expressions:

1. The following selects all the nodes that you think should be selected :

 /*/*[Vacancy and not(Vacancy[. < 1000 or . > 1100])] 
  • The following selects all the nodes that you think should be selected, and all those that you are not sure about. It does not select the node, which you definitely should not be selected :

/*/*[not(Vacancy) or Vacancy[. > 1000 and not(. > 1100)]]

This XSLT transform can be used to validate XPath expressions :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="/"> <xsl:copy-of select= "/*/*[Vacancy and not(Vacancy[. &lt; 1000 or . > 1100])] "/> =============================== <xsl:copy-of select= "/*/*[not(Vacancy) or Vacancy[. > 1000 and not(. > 1100)]] "/> </xsl:template> </xsl:stylesheet> 

when applied to the provided XML document :

 <results> <Building><!--Should this be selected?--></Building> <Building><!--Should be selected--> <Vacancy><sqft>1050</sqft></Vacancy> </Building> <Building><!--Should be selected--> <Vacancy><sqft>1025</sqft></Vacancy> <Vacancy><sqft>1075</sqft></Vacancy> </Building> <Building><!--Shouldn't be selected--> <Vacancy><sqft>10</sqft></Vacancy> <Vacancy><sqft>50</sqft></Vacancy> </Building> <Building><!--Should this be selected?--> <Vacancy><sqft>1050</sqft></Vacancy> <Vacancy><sqft>2000</sqft></Vacancy> </Building> <Building><!--Should this be selected?--> <Vacancy><sqft>900</sqft></Vacancy> <Vacancy><sqft>1040</sqft></Vacancy> </Building> <Building><!--Shouldn't be selected--> <Vacancy><sqft>10500</sqft></Vacancy> </Building> <Building><!--Shouldn't be selected--> <Vacancy><sqft>900</sqft></Vacancy> <Vacancy><sqft>1000</sqft></Vacancy> <Vacancy><sqft>2000</sqft></Vacancy> <Vacancy><sqft>500</sqft></Vacancy> </Building> </results> 

The required, correct results are created :

 <Building><!--Should be selected--> <Vacancy> <sqft>1050</sqft> </Vacancy> </Building> <Building><!--Should be selected--> <Vacancy> <sqft>1025</sqft> </Vacancy> <Vacancy> <sqft>1075</sqft> </Vacancy> </Building> =============================== <Building><!--Should this be selected?--></Building> <Building><!--Should be selected--> <Vacancy> <sqft>1050</sqft> </Vacancy> </Building> <Building><!--Should be selected--> <Vacancy> <sqft>1025</sqft> </Vacancy> <Vacancy> <sqft>1075</sqft> </Vacancy> </Building> <Building><!--Should this be selected?--> <Vacancy> <sqft>1050</sqft> </Vacancy> <Vacancy> <sqft>2000</sqft> </Vacancy> </Building> <Building><!--Should this be selected?--> <Vacancy> <sqft>900</sqft> </Vacancy> <Vacancy> <sqft>1040</sqft> </Vacancy> </Building> 
+1
source

All Articles