Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XPath-除第一个特定元素外的所有后续同级元素_Xml_Xhtml_Xpath - Fatal编程技术网

Xml XPath-除第一个特定元素外的所有后续同级元素

Xml XPath-除第一个特定元素外的所有后续同级元素,xml,xhtml,xpath,Xml,Xhtml,Xpath,假设我正在查询一个xhtml文档,我想用id='target'查询表后面的所有同级。另外,我既不想要这个特定元素的第一个同级,也不想要这个特定元素的第一个同级。以下是我能想到的最好的: //table[@id='target']/following-sibling::*[not(self::table[1]) and not(self::ol[1])] 然而,这并没有在应该的时候返回任何结果。显然,我不理解其中的一些语法(我找不到好的信息来源)。如果有更熟悉XPath语法的人能帮我一把,我将不

假设我正在查询一个xhtml文档,我想用
id='target'
查询表后面的所有同级。另外,我既不想要这个特定元素的第一个
同级,也不想要这个特定元素的第一个
同级。以下是我能想到的最好的:

//table[@id='target']/following-sibling::*[not(self::table[1]) and not(self::ol[1])]
然而,这并没有在应该的时候返回任何结果。显然,我不理解其中的一些语法(我找不到好的信息来源)。如果有更熟悉XPath语法的人能帮我一把,我将不胜感激。此外,出于纯粹的学术目的,我想知道上面的内容实际上在做什么

更新:

请参阅LarsH的答案以了解我的XPath为什么不工作,并参阅Dimitre的答案以了解可接受的解决方案。

使用
self::
轴时,只会有一个节点,因此我相信
self::*[1]
将始终是正确的。每个节点都将成为其自身
self::
轴上的第一个(也是唯一一个)节点。这意味着括号中的表达式相当于
[非(self::table)和非(self::ol)]
,这意味着所有的表和列表都会被过滤掉

我没有设置测试环境,但我想这可能会更好:

/table[@id='target']/following-sibling::*
    [not(self::table and not(preceding-sibling::table)) and
     not(self::ol    and not(preceding-sibling::ol))]

它需要一些调整,但其想法是过滤掉前面没有同级表的
s,而
ol
s没有前面的同级
ol
s。

首先回答第二个问题:上面所做的是选择以下既不是
也不是
ol
元素的同级

原因如下:
self::table[1]
选择上下文节点的self(如果它通过了
table
元素名测试),并过滤以仅选择self::轴上的第一个节点。self::axis上最多有一个节点通过了元素名测试,因此
[1]
是冗余的
self::table[1]
选择上下文节点,只要它是表元素,而不管它在同级元素中的位置如何。因此
not(self::table[1])
在上下文节点是表元素时返回false,而不管它在同级元素中的位置如何

类似地,对于
self::ol[1]

如何做你想做的事情: @John Kugelman的回答几乎是正确的,但忽略了一个事实,即我们必须在包含
表[@id='target']
之前忽略兄弟元素。我认为不可能在纯XPath1.0中正确执行您是否可以使用XPath 2.0?如果您在浏览器中工作,答案通常是否定的

一些解决办法是:

  • 通过基于其他一些基础(例如属性)进行筛选,跳过第一个后续表同级和第一个后续ol同级
  • 选择
    //table[@id='target']
    作为节点集,将其返回到主机环境(即在XPath之外,例如在JavaScript中),循环通过该节点集;在循环内部:选择
    以下同级::*
    通过XPath,在XPath之外的中迭代,并测试每个结果(XPath之外)以查看它是第一个表还是ol
  • 选择
    //table[@id='target']
    作为节点集,将其返回到主机环境(即在XPath之外,例如在JavaScript中),循环通过该节点集;在循环内部:通过XPath选择
    generate id(以下是sibling::table[1])
    generate id(以下是sibling::ol[1])
    ,将这些值接收到JS变量t1id和o1id中,并使用
    “following-sibling::*[generate-id()!=”+t1id+”和generate-id()的形式为XPath表达式构造一个字符串!='+o1id+']'
    。在XPath中选择该字符串,您就有了答案!:-p
更新:在XSLT 1.0中可以找到解决方案-请参阅@Dimitre。

使用

 /table[@id='target']/following-sibling::*[not(self::table) and not(self::ol)] 
| 
 /table[@id='target']/following-sibling::table[position() > 1]
|
 /table[@id='target']/following-sibling::ol[position() > 1]
这将选择表中不属于
table
和不属于
ol
的所有以下同级,以及位置2或更大的所有
table
同级,以及位置2或更大的所有以下
ol
同级

这正是您想要的:除第一个
后面的兄弟姐妹和第一个
ol
后面的兄弟姐妹外,所有后面的兄弟姐妹


这是纯XPath 1.0,不使用任何XSLT函数。

正如我在回答中所指出的,该解决方案忽略了一个事实,即当您测试以下同级以查看哪个是
[1]
时,目标表不应算作前面的同级。此外,前面的同级测试必须忽略目标表之前的任何表或ol元素。好问题,+1。请参阅我的答案,了解一个选择所需节点的XPath表达式。:)@约翰·库格曼:看看我的amswer,它提供了一个纯而不太复杂的XPath 1.0解决方案。感谢您对我尝试的查询失败原因的精彩解释。我最终使用了Dimitre的XPath来解决这个问题。这正是我所寻找的优雅的解决方案,实际上非常简单。我从来没有想过要得到三个相互排斥的集合的并集,其中包含除这两个元素之外的所有元素。非常感谢。啊,应该好好想想。:-)我在尝试工会的解决方案,但没能实现。尽管输入错误:根据最初的问题,
/
而不是
/
是在
之前需要的。呵呵,出于某种原因,我决定使用联合解决方案是不好的,并特别避免使用它+1感谢你没有像我一样愚蠢。:-)