2011-12-14 92 views
1

我有XML,它由持有各种子节点(包括其他容器节点)的容器节点组成。示例XML会是什么样子......寻找最近的匹配标准的祖先/兄弟姐妹

<CONTAINER> 
    <SEARCHFOR /> 
    <ITEM/> 
    <ITEM/> 
    <ITEM/> 
    <ITEM/> 
    <ITEM/> 
    <CONTAINER> 
     <SEARCHFOR /> 
     <ITEM/> 
     <ITEM/> 
     <CONTAINER> 
      <SEARCHFOR /> 
      <ITEM id="1" /> 
      <ITEM/> 
      <ITEM/> 
      <CONTAINER> 
       <ITEM id="2" /> 
      </CONTAINER> 
     </CONTAINER> 
    </CONTAINER> 
</CONTAINER> 

我想找到最接近(范围)将其项目ID = 2的SEARCHFOR节点。 SEARCHFOR节点可以是ITEM的前同胞或祖先CONTAINER节点的孩子。我有一个XPath表达式,它可以找到范围内符合条件的所有SEARCHFOR节点,但我似乎无法得到它只返回最接近的单个元素。

//ITEM[@id="2"]/ancestor::CONTAINER/SEARCHFOR 

我在Sketchpath测试和将利用XML解析器,可处理的XPath 2.0在Delphi来实现此以便语法也是可接受的。我可以通过获取我的结果并使用Delphi获得感兴趣的代码来完成代码,但如果可能的话,我真的需要在XPath本身内部完成这项工作,以便执行。任何帮助表示赞赏。

感谢, 迈克尔

回答

1

也许这个XPath 2.0表达式回答你的问题:

(//ITEM[@id='2']/(ancestor::CONTAINER/SEARCHFOR|preceding-sibling::SEARCHFOR))[last()] 

它的工作原理是建立在文档顺序元素的序列,那么它选择的最后一个,也就是,给出你的描述,最近的(如果我正确的话)。

+0

最优秀的。谢谢。对于我这个简单的例子,这是完美的,应该适合我的20+行xpath我真的很好。 Ughhh!我的大脑都是,但现在炒了。 – 2011-12-14 15:28:32

1

在反向文档顺序的preceding轴的搜索,所以选择第一个这样的前述元件工作正常(只要我们可以假设SEARCHFOR元件本身不是目标ITEM的祖先):

(//ITEM[@id='2']/preceding::SEARCHFOR[parent::CONTAINER])[1] 

我们是否也可以假设SEARCHFOR元素总是在CONTAINER?如果是这样,那么我们不需要明确的检查,使其更短:

(//ITEM[@id='2']/preceding::SEARCHFOR)[1] 
+0

感谢您的建议。这适用于示例,我会尽量记住这一点以供将来参考,但在我的实际应用程序中,我的xpath与XML相比要复杂得多,上面的第一个建议需要的字符较少。 – 2011-12-14 20:35:49