我正在编写一个递归算法来为给定元素生成唯一的最小XPath。 主要思想是允许在一个文档中选择一个元素(即PC上的chrome中的html元素),并且能够在类似文档中找到相应的元素(即它的移动版本中的相同网站)。
在此过程中,我需要为整个给定文档生成完整的XPath字符串,即对于给定节点,遍历整个树并将所有节点的所有属性附加到字符串。
例如,对于以下文档(所需元素标有“*”):
<?xml version="1.0" encoding="UTF-16"?>
<node>
<node/>
<node id="content">
<node>
<node>
<node id="url_text_field"/>
*<node id="go_button" text="Go">
</node>*
<node id="back_button" text="Back">
</node>
</node>
<node id="webViewPlaceholder">
<node/>
</node>
</node>
</node>
</node>
我的代码生成的XPath:
//*[@id='go_button' and @text='Go' and parent::*[child::*[@id='url_text_field'] and child::*[@id='back_button' and @text='Back'] and parent::*[child::*[@id='webViewPlaceholder'] and parent::*[@id='content']]]]
收益率<node id="go_button" text="Go">
这完全符合要素。
我的问题是,在一个特定情况下(即,当包含所需元素的子树具有相同的“兄弟”)时,我必须使用元素的position()=SOME_NUMBER
(或“索引“node [SOME_NUMBER]
”以唯一标识元素,我遇到语法问题。
例如,对于更复杂的文档(同样,元素标有“*”。索引属性不是原始文档的一部分,只是为了参考而添加):
<?xml version="1.0" encoding="UTF-16"?>
<node>
<node/>
<node id="content" index="a">
<node>
<node>
<node id="url_text_field"/>
<node id="go_button" text="Go" index="a1">
</node>
*<node id="go_button" text="Go" index="a2">
</node>*
<node id="back_button" text="Back">
</node>
</node>
<node id="webViewPlaceholder">
<node/>
</node>
</node>
</node>
<node id="content" index="b">
<node>
<node>
<node id="url_text_field"/>
<node id="go_button" text="Go" index="b1">
</node>
<node id="go_button" text="Go" index="b2">
</node>
<node id="back_button" text="Back">
</node>
</node>
<node id="webViewPlaceholder">
<node/>
</node>
</node>
</node>
</node>
当然,之前的XPath找到了四个元素:
<node id="go_button" text="Go" index="a1"></node>
<node id="go_button" text="Go" index="a2"></node>
<node id="go_button" text="Go" index="b1"></node>
<node id="go_button" text="Go" index="b2"></node>
我尝试在XPath中的各个位置添加位置节点(例如//*[@id='go_button' and @text='Go' and position=2 and parent::*[child::*[@id='url_text_field'] and child::*[@id='back_button' and @text='Back'] and parent::*[child::*[@id='webViewPlaceholder'] and parent::*[@id='content'][1]]]]
不起作用),但找不到匹配第二个“兄弟”子树下的方法第一个“父”子树。
答案 0 :(得分:3)
只需将[postion()=1]
附加到路径表达式 - 这将返回xml中与您的路径匹配的两个节点(索引a1和b1)。如果您只想要第一个,请不要使用//
,而是使用/descendant::
。 //
经常会产生意想不到的后果。
答案 1 :(得分:1)
使用parent :: axis是不可能的,因为它总是只返回一个元素:parent。因此,在[1]之外添加位置谓词将永远不会返回元素。
你可以使用http://xsltransform.net/jyyiVhj来解决问题,但你找不到任何解决方案。
您必须创建一个不同的策略来创建一个返回唯一元素的有效xpath。
答案 2 :(得分:1)
解决方案是使用索引节点而不是调用position
我用圆括号包装整个xpath表达式,并添加索引:
(xpath_expression)[index]