1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from translate.misc.typecheck import accepts, Self
27 """A class which is used to build XPath-like paths as a DOM tree is
28 walked. It keeps track of the number of times which it has seen
29 a certain tag, so that it will correctly create indices for tags.
30
31 Initially, the path is empty. Thus
32 >>> xb = XPathBreadcrumb()
33 >>> xb.xpath
34 ""
35
36 Suppose we walk down a DOM node for the tag <foo> and we want to
37 record this, we simply do
38 >>> xb.start_tag('foo')
39
40 Now, the path is no longer empty. Thus
41 >>> xb.xpath
42 foo[0]
43
44 Now suppose there are two <bar> tags under the tag <foo> (that is
45 <foo><bar></bar><bar></bar><foo>), then the breadcrumb will keep
46 track of the number of times it sees <bar>. Thus
47
48 >>> xb.start_tag('bar')
49 >>> xb.xpath
50 foo[0]/bar[0]
51 >>> xb.end_tag()
52 >>> xb.xpath
53 foo[0]
54 >>> xb.start_tag('bar')
55 >>> xb.xpath
56 foo[0]/bar[1]
57 """
58
60 self._xpath = []
61 self._tagtally = [{}]
62
63 @accepts(Self(), unicode)
65 tally_dict = self._tagtally[-1]
66 tally = tally_dict.get(tag, -1) + 1
67 tally_dict[tag] = tally
68 self._xpath.append((tag, tally))
69 self._tagtally.append({})
70
72 self._xpath.pop()
73 self._tagtally.pop()
74
76
77 def str_component(component):
78 tag, pos = component
79 return u"%s[%d]" % (tag, pos)
80 return u"/".join(str_component(component) for component in self._xpath)
81
82 xpath = property(_get_xpath)
83