这两天研究 HTML 的 DOM 需要寻找某个 Element 元素的完整 XPath 路径,由于使用的是 PHP Simple HTML DOM Parser 开源库,这个库类的使用方法几乎兼容 Javascript 的 DOM 语法并附带 DOM 选择器。虽然功能强大但是并不能直接获取 Element 的 XPath。这个怎么办呢,依稀记得 Firebug 有一个功能,选择某个元素在它的控制台可以显示 XPath。嗯,着手实践一下发现不仅可以显示而且还可以复制 XPath。
于是想,如果可以找到 Javascript 版的相关代码就一定可以改成 PHP 版本的,结果在 Google 搜索找到了…
1var elt = document.getElementById('table');
2var xpath = getElementXPath(elt);alert(xpath);
3
4// Get full XPath of an element
5function getElementXPath(elt){
6 var path = "";
7 for (; elt && elt.nodeType == 1; elt = elt.parentNode)
8 {
9 idx = getElementIdx(elt);
10 xname = elt.tagName;
11 if (idx > 1) xname += "[" + idx + "]";
12 path = "/" + xname + path;
13 }
14 return path;
15}
16
17// Get Idx of an element
18function getElementIdx(elt){
19 var count = 1;
20 for (var sib = elt.previousSibling; sib ; sib = sib.previousSibling)
21 {
22 if(sib.nodeType == 1 && sib.tagName == elt.tagName) count++
23 }
24 return count;
25}
PHP 改进版:
1// Use it before import PHP Simple HTML DOM Parser
2$html = file_get_html('http://www.google.com/');
3
4// find a sample element by id
5$elt1 = $html->find('#footer', 0);
6
7// find a sample element by tag name
8$elt2= $html->find('div', 10);
9
10// it will return if found it: [@id="footer"]
11$xpath = getElementXPath($elt1);
12
13// it will return if found it: html/body/div[10]
14$xpath = getElementXPath($elt2);
15
16function getElementXPath($elt){
17 $path = '';
18 $first = TRUE;
19 for(; ($elt AND $elt->nodetype == 1); $elt = $elt->parent())
20 {
21 $xname = $elt->tag;
22 $idx = getElementIdx($elt);
23 if ($first AND isset($elt->attr['id']))
24 {
25 $path = '//*[@id="' . $elt->attr['id'] . '"]';
26 break;
27 }
28
29 if ($idx > 1)
30 {
31 %xname .= '[' . $idx . ']';
32 }
33
34 $path = '/'.$xname.$path;
35 $first = FALSE;
36 }
37
38 return $path;
39}
40
41function getElementIdx($elt){
42 $count = 1;
43 for($sib = $elt->prev_sibling(); $sib ; $sib = $sib->prev_sibling())
44 {
45 if($sib->nodetype == 1 && $sib->tag == $elt->tag)
46 {
47 $count++;
48 }
49 }
50 return $count;
51}
大家同样可以把上面的代码直接 crack 到 PHP Simple HTML DOM Parser 库中。