pythonらしいというか。ま、python に限らず、動的な言語はだいたいこんなことが出来ますな。
python で、xpath の simplifyで、こんなのを書いた:
1 # -*- coding: utf-8 -*-
2 from xml.etree.ElementPath import xpath_tokenizer
3
4 def xpath_simplify_tokenize(xpath, nsmaps={}):
5 depth = 0
6 for tok in xpath_tokenizer(xpath, nsmaps):
7 if tok[0] == '[':
8 depth += 1
9 elif tok[0] == ']':
10 depth -= 1
11 elif depth == 0:
12 yield tok
13
14 print(list(
15 xpath_simplify_tokenize(
16 '/books/author[last-name [position()=1]= "Bob"]')))
17
18 # ancestor::は無論「namespace」ではないが、xpath_tokenizer は「馬鹿」なので。
19 # そもそも xpath フルスペックを扱おうとするものではないので…。
20 # 戻りには {ancestor}: のように、python 文字列の format が扱える形("{a}".format(a=1)という
21 # 具合)で返るので、nsmaps の工夫で多分なんとかなる。
22 print(list(
23 xpath_simplify_tokenize(
24 'ancestor::author[last-name [position()=1]= "Bob"]',
25 {'ancestor': 'ancestor'})))
これな、こんなんしとけばいいのな:
1 # -*- coding: utf-8 -*-
2 from xml.etree.ElementPath import xpath_tokenizer
3
4 class _M(object):
5 def __getitem__(self, name):
6 return name
7
8 def xpath_simplify_tokenize(xpath, nsmaps=_M()):
9 depth = 0
10 for tok in xpath_tokenizer(xpath, nsmaps):
11 if tok[0] == '[':
12 depth += 1
13 elif tok[0] == ']':
14 depth -= 1
15 elif depth == 0:
16 yield tok
17
18 print(list(
19 xpath_simplify_tokenize(
20 '/books/author[last-name [position()=1]= "Bob"]')))
21
22 print(list(
23 xpath_simplify_tokenize(
24 'ancestor::author[last-name [position()=1]= "Bob"]')))
class _M
のインスタンスは「obj['xyz']
」に対して単に「'xyz'
」をそのまま返す。ので、今の場合、ancestor
をそのまま返すので、結果、実行結果は前回と全く同じ:
1 me@host: ~$ python aaa2.py
2 [('/', ''), ('', 'books'), ('/', ''), ('', 'author')]
3 [('', '{ancestor}:author')]
4 me@host: ~$
となって、めでたし。