当使用大于和小于?时,xpath查询返回错误的值

时间:2010-10-26 22:37:55

标签: xml xpath

此查询返回的值小于1000.它应该只返回1000到1100之间的值。为什么会这样?

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

查询将返回以下建筑物,其空置面积小于1000平方英尺,大于1100平方英尺:

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

为什么它包含在结果中?

示例数据:

<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>

感谢。

5 个答案:

答案 0 :(得分:8)

示例Building有一个空位子,平方英尺为2000,所以Vacancy/sqft > 1000成功。它有一个sqft为1000(900和500)的孩子,所以Vacancy/sqft < 1100成功。因此,xpath选择Building。

比较表达式(例如Vacancy/sqft <= 1000)隐含地使用“there exists”限定 - 如“存在一个具有平方英尺的子项且值>&gt; 1000的空缺孩子” - 因为{{ 1}}是set of nodes,而不是单个节点。此外,每个比较都有自己的资格,因此Vacancy/sqft中的sqft不需要与Vacancy/sqft > 1000中的sqft相同。请注意,Vacancy/sqft < 1100是一个节点集;谓词//results/Buildings分别应用于集合中的每个项目,这就是限定符没有问题的原因。将原始xpath翻译成英文,我们得到:

  

选择建筑物(在结果中),使得1 = 1并且存在空位面积&gt; 1000,并且存在空位面积&lt; 1100。

让我们使用所需查询的英语声明,使其更接近逻辑语句,到达以下之一:

  

选择建筑物(在结果中),使得存在具有平方英尺的空位,使得其> 1000并且它是&lt; 1100

     

选择建筑物(在结果中),使得存在空位,使得平方英尺&gt; 1000和平方英尺&lt; 1100

前者导致jasso的解决方案,后者导致:

[...]

原始解决方案

(注意:这回答了原来的问题,当时不清楚OP想要什么。这个技术可能对其他有类似问题但需求不同的人有用,所以我把它留在了。)

尝试条件的逻辑双重否定:

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

该谓词包括对空缺儿童进行的测试,以筛选出其他原本无效的建筑物,即没有空位的建筑物。该解决方案的英语等同于:

  

选择建筑物(在结果中),使得建筑物有空位,并且不存在空位面积<= 1000或者存在空位面积&gt; = 1100

用更少的话来说:

  

选择所有空置的建筑物,其中没有空位<= 1000平方英尺或> = 1100平方英尺。

用更少的话来说:

  

选择所有空置的建筑物,所有空位都在1000到1100平方英尺之间。

答案 1 :(得分:7)

您是否还需要匹配超出标准的平方英尺的建筑物,但至少有一平方英尺,介于1000-1100之间

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

如果是,则使用XPath表达式

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

它还会选择没有<Vacancy>元素的建筑物(根据要求)。

答案 2 :(得分:3)

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

此查询返回的值较少   它应该只返回   值在1000和1100之间。为什么   是什么?

来自http://www.w3.org/TR/xpath/#booleans

  

如果要比较的一个对象是a   node-set和另一个是数字,   那么比较将是真的,如果   并且只有在节点中有节点   node-set这样的结果   进行比较   要比较的数字和   转换字符串值的结果   该节点使用的数字   数字函数是真的。

节点集比较是存在性比较Vacancy/sqft > 1000表示:是否至少有一个Vacancy/sqft大于1000?

如果你想选择Building个包含Vacancy/sqft个大孩子的元素,并且所有这些元素都在范围内(1000,1100),这个XPath表达式:

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

答案 3 :(得分:1)

尝试将xpath更改为:

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

我怀疑它正在将你的Vacancy/sqft节点视为文本,这可能会导致一些奇怪的现象......

我删除了你的1 = 1和额外的parens,因为我没有看到他们的需要。重点是尝试number函数。

<强>更新

这个有点奇怪,但它会抓住你想要的那个加上你不确定的那个(Should this be selected?):

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

如果你想排除那个:

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

此外,我正在使用this site来发送我的xpath文本,如果它们之间存在某种根本区别,那么Objective-c让我知道...

答案 4 :(得分:1)

以下是两个XPath表达式:

<强> 1。以下选择您认为应 的所有节点:

/*/*[Vacancy and not(Vacancy[. < 1000 or . > 1100])]
  1. 以下选择您认为应该选择的所有节点以及您不确定的所有节点。它选择您不确定的任何节点
  2. /*/*[not(Vacancy) or Vacancy[. > 1000 and not(. > 1100)]]

    此XSLT转换可用于验证XPath表达式的正确性

    <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>
    

    应用于提供的XML文档

    <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>
    

    生成所需的正确结果

    <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>