PKb.h5“×2EGG-INFO/dependency_links.txt PKb.h5Du(EGG-INFO/namespace_packages.txtpdis PKb.h5ÎÛROBBEGG-INFO/PKG-INFOMetadata-Version: 1.0 Name: PDIS-XPath Version: 0.3 Summary: Pure-Python XPath evaluator based on ElementTree Home-page: http://pdis.hiit.fi/pdis/download/ Author: Ken Rimey Author-email: rimey@hiit.fi License: MIT License Description: This is a pure-Python XPath evaluator based on ElementTree. It supports a substantial fraction of the XPath 1.0 specification, notwithstanding the limitation that only the self, child, and attribute axes are supported. The parser underlying the evaluator attempts to handle all of XPath 1.0. Platform: UNKNOWN PKb.h5NÔ­ EGG-INFO/requires.txtelementtreePKb.h5Æ(|__EGG-INFO/SOURCES.txtDEPENDENCIES INSTALL LICENSE README ez_setup.py setup.py PDIS_XPath.egg-info/PKG-INFO PDIS_XPath.egg-info/SOURCES.txt PDIS_XPath.egg-info/dependency_links.txt PDIS_XPath.egg-info/namespace_packages.txt PDIS_XPath.egg-info/requires.txt PDIS_XPath.egg-info/top_level.txt pdis/__init__.py pdis/xpath/__init__.py pdis/xpath/atoms.py pdis/xpath/bench.py pdis/xpath/context.py pdis/xpath/data_model.py pdis/xpath/evaluate.py pdis/xpath/lexer.py pdis/xpath/parser.py pdis/xpath/syntax.py pdis/xpath/xpath_exceptions.py pdis/xpath/tests/__init__.py pdis/xpath/tests/test_evaluate.py pdis/xpath/tests/test_parser.py PKb.h5Du(EGG-INFO/top_level.txtpdis PKb.h5“×2EGG-INFO/zip-safe PKD£f5(åØ88pdis/__init__.py__import__('pkg_resources').declare_namespace(__name__) PKb.h5 Ü?ÀÙÙpdis/__init__.pyc;ò ÑüOEc@sedƒieƒdS(s pkg_resourcesN(s __import__sdeclare_namespaces__name__(((s2build/bdist.darwin-8.8.1-i386/egg/pdis/__init__.pys?sPKƒ¢f5ëšÊ" " pdis/xpath/__init__.py# # pdis.xpath (__init__.py) # # Copyright 2004 Helsinki Institute for Information Technology (HIIT) # and the authors. All rights reserved. # # Authors: Ken Rimey # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ Package-level definitions for the xpath package Most applications need only import this file with "import pdis.xpath" or "from pdis.xpath import ...". """ try: from pdis.lib.element import XML except ImportError: from elementtree.ElementTree import XML from pdis.xpath.parser import parse_xpath from pdis.xpath.context import Context from pdis.xpath.data_model import is_node_set from pdis.xpath.xpath_exceptions import * def evaluate(xpath, document): element = XML(document) return compile(xpath).evaluate(element) _cache = {} def compile(xpath, namespace_mapping = None): # We only cache when there is no namespace mapping. Hopefully # that is the common case. if namespace_mapping: return XPath(xpath, namespace_mapping) p = _cache.get(xpath) if p is None: p = XPath(xpath) if len(_cache) >= 100: _cache.popitem() _cache[xpath] = p return p class XPath: """ Preparsed xpath expression """ def __init__(self, xpath, namespace_mapping = None): """ Initialize an XPath instance. As a special case, if the xpath expression is the empty string, the evaluate() method will always return a true value. """ self.xpath = xpath self.namespace_mapping = namespace_mapping if not xpath: self.parsed_xpath = parse_xpath("1") else: self.parsed_xpath = parse_xpath(xpath) def evaluate(self, element): context = Context(element, self.namespace_mapping) result = self.parsed_xpath.evaluate(context) if is_node_set(result) and not isinstance(result, list): # Node sets can be all sorts of things internally, but # let's normalize them to lists at this point. result = list(result) return result PKb.h5¶ÅÔn pdis/xpath/__init__.pyc;ò gûOEc@sšdZydklZWn ej odklZnXdklZdklZdk l Z dk Td„Z hZ ed„Zdfd „ƒYZd S( s™ Package-level definitions for the xpath package Most applications need only import this file with "import pdis.xpath" or "from pdis.xpath import ...". (sXML(s parse_xpath(sContext(s is_node_set(s*cCs#t|ƒ}t|ƒi|ƒSdS(N(sXMLsdocumentselementscompilesxpathsevaluate(sxpathsdocumentselement((s8build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/__init__.pysevaluate.s cCsw|ot||ƒSnti|ƒ}|tjo;t|ƒ}ttƒdjotiƒn|t| # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ XPath syntax nodes for atoms """ from pdis.xpath.xpath_exceptions import \ XPathNotImplementedError, XPathEvaluationError # # Base classes # # These are generally abstract, except that the lexer instantiates # QNames for its internal use. # class Name: def __init__(self, s): self.name = s def __str__(self): return self.name class QName: def __init__(self, s1, s2=None): if s2 is None: self.prefix = None self.local_part = s1 else: self.prefix = s1 self.local_part = s2 def __str__(self): if self.prefix is None: return self.local_part else: return "%s:%s" % (self.prefix, self.local_part) # # Atomic nodes never present in the final syntax tree # # These are used internal by the lexer and parser. NameTest and # NodeType are used as parameters in LocationStep nodes. FunctionName # is used as a parameter in FunctionCall nodes. # class AxisName(Name): pass class NodeType(Name): pass class NameTest(QName): # Here we allow local_part to take the otherwise illegal value "*". def expand(self, context): if self.prefix is None: uri = None else: uri = context.namespace_mapping.get(self.prefix) if uri is None: raise XPathEvaluationError, \ 'Unbound namespace prefix "%s".' % self.prefix if self.local_part == '*': name = None else: name = self.local_part return (uri, name) class FunctionName(QName): pass # # Atomic nodes # class Literal: """ Node representing a string literal """ def __init__(self, s): self.value = s def __str__(self): if '"' in self.value: return "'%s'" % self.value else: return '"%s"' % self.value def evaluate(self, context): return self.value class Number: """ Node representing a double-precision floating-point number """ def __init__(self, value): self.value = float(value) def __str__(self): return str(self.value) def evaluate(self, context): return self.value class VariableReference(QName): """ Variable reference node """ def __str__(self): return "$%s" % QName.__str__(self) def evaluate(self, context): raise XPathNotImplementedError, "Variable references not implemented." PKb.h5ã,v£((pdis/xpath/atoms.pyc;ò gûOEc@s×dZdklZlZdfd„ƒYZdfd„ƒYZdefd„ƒYZdefd „ƒYZd efd „ƒYZd efd „ƒYZ dfd„ƒYZ dfd„ƒYZ defd„ƒYZ dS(s XPath syntax nodes for atoms (sXPathNotImplementedErrorsXPathEvaluationErrorsNamecBstZd„Zd„ZRS(NcCs ||_dS(N(sssselfsname(sselfss((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys__init__,scCs |iSdS(N(sselfsname(sself((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys__str__/s(s__name__s __module__s__init__s__str__(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysName+s sQNamecBstZed„Zd„ZRS(NcCs9|tjot|_||_n||_||_dS(N(ss2sNonesselfsprefixss1s local_part(sselfss1ss2((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys__init__3s     cCs3|itjo |iSnd|i|ifSdS(Ns%s:%s(sselfsprefixsNones local_part(sself((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys__str__;s (s__name__s __module__sNones__init__s__str__(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysQName2s sAxisNamecBstZRS(N(s__name__s __module__(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysAxisNameIssNodeTypecBstZRS(N(s__name__s __module__(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysNodeTypeLssNameTestcBstZd„ZRS(NcCs|itjo t}n7|ii|iƒ}|tjotd|i‚n|idjo t}n |i}||fSdS(NsUnbound namespace prefix "%s".s*( sselfsprefixsNonesuriscontextsnamespace_mappingsgetsXPathEvaluationErrors local_partsname(sselfscontextsnamesuri((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysexpandQs    (s__name__s __module__sexpand(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysNameTestOss FunctionNamecBstZRS(N(s__name__s __module__(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys FunctionNameassLiteralcBs)tZdZd„Zd„Zd„ZRS(s, Node representing a string literal cCs ||_dS(N(sssselfsvalue(sselfss((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys__init__lscCs.d|ijod|iSn d|iSdS(Ns"s'%s's"%s"(sselfsvalue(sself((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys__str__oscCs |iSdS(N(sselfsvalue(sselfscontext((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysevaluateus(s__name__s __module__s__doc__s__init__s__str__sevaluate(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysLiteralhs   sNumbercBs)tZdZd„Zd„Zd„ZRS(sD Node representing a double-precision floating-point number cCst|ƒ|_dS(N(sfloatsvaluesself(sselfsvalue((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys__init__|scCst|iƒSdS(N(sstrsselfsvalue(sself((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys__str__scCs |iSdS(N(sselfsvalue(sselfscontext((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysevaluate‚s(s__name__s __module__s__doc__s__init__s__str__sevaluate(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysNumberxs   sVariableReferencecBs tZdZd„Zd„ZRS(s! Variable reference node cCsdti|ƒSdS(Ns$%s(sQNames__str__sself(sself((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys__str__‰scCs td‚dS(Ns$Variable references not implemented.(sXPathNotImplementedError(sselfscontext((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysevaluateŒs(s__name__s __module__s__doc__s__str__sevaluate(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pysVariableReference…s  N( s__doc__spdis.xpath.xpath_exceptionssXPathNotImplementedErrorsXPathEvaluationErrorsNamesQNamesAxisNamesNodeTypesNameTests FunctionNamesLiteralsNumbersVariableReference( sNodeTypesNamesAxisNamesXPathEvaluationErrorsXPathNotImplementedErrorsQNamesVariableReferencesNumbersLiterals FunctionNamesNameTest((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/atoms.pys?s  PKƒ¢f5^kÊ2ÊÊpdis/xpath/bench.py# # pdis.xpath.bench # # Copyright 2004 Helsinki Institute for Information Technology (HIIT) # and the authors. All rights reserved. # # Authors: Ken Rimey # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from time import time try: from pdis.lib.element import XML except ImportError: from elementtree.ElementTree import XML from pdis.xpath import XPath N = 10000 def bench(path, document): t0 = time() for i in range(N): element = XML(document) t1 = time() print t1 - t0, "(parse document)" t0 = time() for i in range(N): xpath = XPath(path) t1 = time() print t1 - t0, "(parse path)" t0 = time() for i in range(N): result = xpath.evaluate(element) t1 = time() print t1 - t0, "(evaluate)" print 'result =', result document = "blahorangeblah" bench("/*/color = 'orange'", document) bench("/*/color = 'green'", document) PKb.h5_nGópdis/xpath/bench.pyc;ò gûOEc@sdklZydklZWn ej odklZnXdklZdZd„ZdZ ede ƒede ƒdS( (stime(sXML(sXPathi'cCsÖtƒ}x ttƒD]}t|ƒ}qWtƒ}||GdGHtƒ}x ttƒD]}t |ƒ}qXWtƒ}||GdGHtƒ}x#ttƒD]}|i |ƒ}qšWtƒ}||GdGHdG|GHdS(Ns(parse document)s (parse path)s (evaluate)sresult =(stimest0srangesNsisXMLsdocumentselementst1sXPathspathsxpathsevaluatesresult(spathsdocumentsxpathsist1st0sresultselement((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/bench.pysbench(s&            sDblahorangeblahs/*/color = 'orange's/*/color = 'green'N( stimespdis.lib.elementsXMLs ImportErrorselementtree.ElementTrees pdis.xpathsXPathsNsbenchsdocument(sXMLsXPathsdocumentsNstimesbench((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/bench.pys?s    PKƒ¢f5w«Ò‰‰pdis/xpath/context.py# # pdis.xpath.context # # Copyright 2004 Helsinki Institute for Information Technology (HIIT) # and the authors. All rights reserved. # # Authors: Ken Rimey # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ XPath evaluation context """ class Context: def __init__(self, element, namespace_mapping = None): self.root = (element,) if namespace_mapping is None: self.namespace_mapping = {} else: self.namespace_mapping = namespace_mapping self.node = self.root self.position = 1 self.size = 1 def clone(self): context = Context(None) context.root = self.root context.namespace_mapping = self.namespace_mapping context.node = self.node context.position = self.position context.size = self.size return context def get_root(self): return self.root PKb.h5< ‰]XXpdis/xpath/context.pyc;ò gûOEc@sdZdfd„ƒYZdS(s XPath evaluation context sContextcBs&tZed„Zd„Zd„ZRS(NcCsQ|f|_|tjo h|_n ||_|i|_d|_d|_dS(Ni(selementsselfsrootsnamespace_mappingsNonesnodespositionssize(sselfselementsnamespace_mapping((s7build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/context.pys__init__"s      cCsPttƒ}|i|_|i|_|i|_|i|_|i|_|SdS(N( sContextsNonescontextsselfsrootsnamespace_mappingsnodespositionssize(sselfscontext((s7build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/context.pysclone-s      cCs |iSdS(N(sselfsroot(sself((s7build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/context.pysget_root8s(s__name__s __module__sNones__init__sclonesget_root(((s7build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/context.pysContext!s N(s__doc__sContext(sContext((s7build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/context.pys?sPKƒ¢f5Ý¡™_EEpdis/xpath/data_model.py# # pdis.xpath.data_model # # Copyright 2004 Helsinki Institute for Information Technology (HIIT) # and the authors. All rights reserved. # # Authors: Ken Rimey # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ XML data model Our model is element tree extended with a root node. We support four of the XPath data model node types: * root node -- singleton tuple containing an Element. * element node -- Element. * text or attribute node -- string. We represent node sets as sequences. They can be lists, but we also take advantage of the fact that a root or element node is effectively a sequence containing its element children. """ try: from pdis.lib.element import iselement except ImportError: from elementtree.ElementTree import iselement def is_node_set(x): return isinstance(x, (list, tuple)) or iselement(x) def join_node_sets(x, y): if len(x) == 0: return y elif len(y) == 0: return x else: if not isinstance(x, list): x = list(x) if not isinstance(y, list): y = list(y) return x + y def is_root_node(node): return isinstance(node, tuple) def is_element_node(node, uri = None, name = None): if not iselement(node): return False if uri is None and name is None: return True element_uri, element_name = get_expanded_name(node) if uri != element_uri: return False return name is None or name == element_name def is_text_node(node): # Note that this predicate also returns True for attribute nodes. return isinstance(node, (str, unicode)) def get_string_value(node): return "".join(get_text_nodes(node)) def get_expanded_name(element): tag = element.tag if tag[:1] != "{": return (None, tag) else: return tag[1:].split("}", 1) def get_attribute_value(node, uri, name): if is_element_node(node): if uri: name = "{%s}%s" % (uri, name) return node.get(name) else: return None def get_child_element_nodes(node, uri = None, name = None): if is_root_node(node): if is_element_node(node[0], uri, name): return node # Container with one element. else: return () elif is_text_node(node): return () else: assert is_element_node(node) if name: if uri: name = "{%s}%s" % (uri, name) return [x for x in node if x.tag == name] elif uri: prefix = "{%s}" % uri return [x for x in node if x.tag.startswith(prefix)] else: return node # Container with child elements. def get_child_text_nodes(node): result = [] if is_element_node(node): if node.text: result.append(node.text) for child in node: if child.tail: result.append(child.tail) return result def get_child_nodes(node): if is_root_node(node): return node # Container with one element. elif is_text_node(node): return () else: assert is_element_node(node) # If there are no text children, we can simply return the element, # which acts as a container for its element children. if not node.text: for child in node: if child.tail: break else: return node # Container with child elements. # Collect the text and element children. result = [] if node.text: result.append(node.text) for child in node: result.append(child) if child.tail: result.append(child.tail) return result def get_text_nodes(node): # This is something like descendant-or-self::text(), except that # it also returns the given node if it is an attribute node. if is_root_node(node): return get_text_nodes(node[0]) elif is_text_node(node): return [node] else: assert is_element_node(node) result = [] push_text_nodes(result, node) return result def push_text_nodes(buffer, element): if element.text: buffer.append(element.text) for child in element: push_text_nodes(buffer, child) if child.tail: buffer.append(child.tail) PKb.h5þƒCÈpdis/xpath/data_model.pyc;ò gûOEc@s¿dZydklZWn ej odklZnXd„Zd„Zd„Zeed„Z d„Z d„Z d„Z d „Z eed „Zd „Zd „Zd „Zd„ZdS(s¬ XML data model Our model is element tree extended with a root node. We support four of the XPath data model node types: * root node -- singleton tuple containing an Element. * element node -- Element. * text or attribute node -- string. We represent node sets as sequences. They can be lists, but we also take advantage of the fact that a root or element node is effectively a sequence containing its element children. (s iselementcCs$t|ttfƒp t|ƒSdS(N(s isinstancesxsliststuples iselement(sx((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pys is_node_set1scCs„t|ƒdjo|Snft|ƒdjo|SnKt|tƒ ot|ƒ}nt|tƒ ot|ƒ}n||SdS(Ni(slensxsys isinstanceslist(sxsy((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pysjoin_node_sets4scCst|tƒSdS(N(s isinstancesnodestuple(snode((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pys is_root_node@scCszt|ƒ otSn|tjo |tjotSnt|ƒ\}}||jotSn|tjp ||jSdS(N( s iselementsnodesFalsesurisNonesnamesTruesget_expanded_names element_uris element_name(snodesurisnames element_uris element_name((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pysis_element_nodeCs cCst|ttfƒSdS(N(s isinstancesnodesstrsunicode(snode((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pys is_text_nodeMscCsdit|ƒƒSdS(Ns(sjoinsget_text_nodessnode(snode((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pysget_string_valueQscCs@|i}|d djot|fSn|diddƒSdS(Nis{s}(selementstagsNonessplit(selementstag((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pysget_expanded_nameTs cCsAt|ƒo,|od||f}n|i|ƒSntSdS(Ns{%s}%s(sis_element_nodesnodesurisnamesgetsNone(snodesurisname((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pysget_attribute_value[s  cCst|ƒo't|d||ƒo|SqfSnÞt|ƒofSnÉt|ƒpt‚|oX|od||f}ngi}|D]$}|i |jo||ƒqq~SnV|oJd|}gi}|D]'}|i i |ƒo||ƒqÛqÛ~Sn|SdS(Nis{%s}%ss{%s}( s is_root_nodesnodesis_element_nodesurisnames is_text_nodesAssertionErrorsappends_[1]sxstagsprefixs startswith(snodesurisnamesprefixs_[1]sx((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pysget_child_element_nodescs  = @cCslg}t|ƒoQ|io|i|iƒnx0|D]$}|io|i|iƒq8q8Wn|SdS(N(sresultsis_element_nodesnodestextsappendschildstail(snodesresultschild((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pysget_child_text_nodesws   cCsÙt|ƒo|SnÁt|ƒofSn¬t|ƒpt‚|i o(x%|D]}|ioPqPqPW|Sng}|io|i |iƒnx9|D]1}|i |ƒ|io|i |iƒqœqœW|SdS(N( s is_root_nodesnodes is_text_nodesis_element_nodesAssertionErrorstextschildstailsresultsappend(snodesresultschild((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pysget_child_nodess(        cCsft|ƒot|dƒSnDt|ƒo |gSn,t|ƒpt‚g}t||ƒ|SdS(Ni(s is_root_nodesnodesget_text_nodess is_text_nodesis_element_nodesAssertionErrorsresultspush_text_nodes(snodesresult((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pysget_text_nodesœs    cCs^|io|i|iƒnx9|D]1}t||ƒ|io|i|iƒq%q%WdS(N(selementstextsbuffersappendschildspush_text_nodesstail(sbufferselementschild((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pyspush_text_nodes©s   N(s__doc__spdis.lib.elements iselements ImportErrorselementtree.ElementTrees is_node_setsjoin_node_setss is_root_nodesNonesis_element_nodes is_text_nodesget_string_valuesget_expanded_namesget_attribute_valuesget_child_element_nodessget_child_text_nodessget_child_nodessget_text_nodesspush_text_nodes(spush_text_nodessget_string_valuesget_child_element_nodessget_attribute_valuesget_child_nodessget_expanded_namesget_text_nodess is_node_sets is_root_nodesis_element_nodesget_child_text_nodess iselementsjoin_node_setss is_text_node((s:build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/data_model.pys?*s"        PKƒ¢f5Aóx7474pdis/xpath/evaluate.py# # pdis.xpath.evaluate # # Copyright 2004 Helsinki Institute for Information Technology (HIIT) # and the authors. All rights reserved. # # Authors: Ken Rimey # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ Subroutines used by evaluate() methods in syntax.py """ try: from math import floor, ceil except ImportError: from pdis.lib.compat import floor, ceil from pdis.xpath.xpath_exceptions import \ XPathNotImplementedError, XPathEvaluationError from pdis.xpath.data_model import * from pdis.xpath import atoms def is_string(x): return isinstance(x, (str, unicode)) def is_number(x): return isinstance(x, float) def is_boolean(x): # Booleans are int in Python 2.2 and bool in Python 2.3. return isinstance(x, type(True)) def to_string(x): if is_string(x): return x elif is_node_set(x): if len(x) > 0: return get_string_value(x[0]) else: return "" elif is_number(x): if int(x) == x: x = int(x) return str(x) elif is_boolean(x): if x: return "true" else: return "false" else: assert False def to_number(x): if is_node_set(x): x = to_string(x) try: return float(x) except ValueError: raise XPathEvaluationError, \ 'Could not convert "%s" to number.' % x def to_boolean(x): if is_boolean(x): return x elif is_number(x): return x != 0 elif is_node_set(x): return len(x) > 0 elif is_string(x): return len(x) > 0 else: assert False relational_transpose = { '=' : '=', '!=' : '!=', '<' : '>', '>' : '<', '<=' : '>=', '>=' : '<=', } def compare(op, x, y): x_is_node_set = is_node_set(x) y_is_node_set = is_node_set(y) if x_is_node_set and y_is_node_set: x = map(get_string_value, x) y = map(get_string_value, y) for xx in x: for yy in y: if compare2(op, xx, yy): return True return False elif x_is_node_set or y_is_node_set: if y_is_node_set: op = relational_transpose[op] x, y = y, x if is_number(y): x = map(get_string_value, x) x = map(to_number, x) for xx in x: if compare2(op, xx, y): return True return False elif is_string(y): x = map(get_string_value, x) for xx in x: if compare2(op, xx, y): return True return False elif is_boolean(y): return compare2(op, to_boolean(x), y) else: return compare2(op, x, y) def compare2(op, x, y): if op in ['=', '!=']: if is_boolean(x) or is_boolean(y): x = to_boolean(x) y = to_boolean(y) elif is_number(x) or is_number(y): x = to_number(x) y = to_number(y) else: x = to_string(x) y = to_string(y) if op == '=': return x == y else: return x != y elif op in ['<', '>', '<=', '>=']: x = to_number(x) y = to_number(y) if op == '<': return x < y elif op == '>': return x > y elif op == '<=': return x <= y elif op == '>=': return x >= y else: assert False else: assert False def do_step(input_node_set, axis, node_test, predicate_list, context): if axis == "self": if isinstance(node_test, atoms.NameTest): uri, name = node_test.expand(context) node_set = [x for x in input_node_set if is_element_node(x, uri, name)] elif isinstance(node_test, atoms.NodeType): if node_test.name == "node": node_set = input_node_set elif node_test.name == "text": # XXX Bug: This also selects attribute nodes. node_set = filter(is_text_node, input_node_set) else: node_set = () else: node_set = () for predicate in predicate_list: node_set = filter_singleton_nodes(node_set, predicate, context) return node_set elif axis == "attribute": if isinstance(node_test, atoms.NameTest): uri, name = node_test.expand(context) if name is None: raise XPathNotImplementedError, \ 'Wildcard attribute references not supported.' node_set = [] for node in input_node_set: value = get_attribute_value(node, uri, name) if value is not None: node_set.append(value) else: raise XPathNotImplementedError, \ 'Only name tests supported for attribute references.' for predicate in predicate_list: node_set = filter_singleton_nodes(node_set, predicate, context) return node_set elif axis == "child": result = [] for context_node in input_node_set: if isinstance(node_test, atoms.NameTest): uri, name = node_test.expand(context) node_set = get_child_element_nodes(context_node, uri, name) elif isinstance(node_test, atoms.NodeType): if node_test.name == "node": node_set = get_child_nodes(context_node) elif node_test.name == "text": node_set = get_child_text_nodes(context_node) else: node_set = () else: node_set = () for predicate in predicate_list: node_set = filter_node_set(node_set, predicate, context) result = join_node_sets(result, node_set) return result else: raise XPathNotImplementedError, '"%s" axis not supported.' % axis def filter_singleton_nodes(node_set, predicate, context_context): result = [] context = context_context.clone() context.size = 1 context.position = 1 for node in node_set: context.node = node if evaluate_predicate(predicate, context): result.append(node) return result def filter_node_set(node_set, predicate, context_context): result = [] context = context_context.clone() context.size = len(node_set) context.position = 0 for node in node_set: context.position += 1 context.node = node if evaluate_predicate(predicate, context): result.append(node) return result def evaluate_predicate(predicate, context): value = predicate.evaluate(context) if is_number(value): return value == context.position else: return to_boolean(value) def do_function_call(name, args, context): if name == "last": check(name, not args) return float(context.size) elif name == "position": check(name, not args) return float(context.position) elif name == "count": check(name, len(args) == 1 and is_node_set(args[0])) # XXX We should make sure the node set doesn't contain any # duplicates. However, that won't be possible when it # contains text or attribute nodes. return float(len(args[0])) elif name == "id": check(name, len(args) == 1) raise XPathNotImplementedError, 'id() not supported.' elif name in ["local-name", "namespace-uri", "name"]: check(name, len(args) <= 1) if args: node_set = args[0] check(name, is_node_set(node_set)) if len(node_set) == 0: return "" node = node_set[0] else: node = context.node if is_root_node(node): uri, local_part = "", "" elif is_element_node(node): uri, local_part = get_expanded_name(node) else: # Text or attribute node. raise XPathNotImplementedError, \ '%s() not supported for this node type.' % name if name == "local-name": return local_part elif name == "namespace-uri": return uri else: assert name == "name" if uri: raise XPathNotImplementedError, \ 'name() not supported for qualified names.' else: return local_part elif name == "string": check(name, len(args) <= 1) if args: return to_string(args[0]) else: return get_string_value(context.node) elif name == "concat": check(name, len(args) >= 2) args = map(to_string, args) return "".join(args) elif name == "starts-with": check(name, len(args) == 2) args = map(to_string, args) return args[0].startswith(args[1]) elif name == "contains": check(name, len(args) == 2) args = map(to_string, args) return args[0].find(args[1]) >= 0 elif name == "substring-before": check(name, len(args) == 2) args = map(to_string, args) k = args[0].find(args[1]) if k == -1: return "" else: return args[0][:k] elif name == "substring-after": check(name, len(args) == 2) args = map(to_string, args) k = args[0].find(args[1]) if k == -1: return "" else: k += len(args[1]) return args[0][k:] elif name == "substring": check(name, len(args) == 2 or len(args) == 3) s = to_string(args[0]) i = int(round(to_number(args[1]))) - 1 if len(args) == 2: i = max(i, 0) return s[i:] else: k = int(round(to_number(args[2]))) j = i + k i = max(i, 0) return s[i:j] elif name == "string-length": check(name, len(args) <= 1) if args: s = to_string(args[0]) else: s = get_string_value(context.node) return float(len(s)) elif name == "normalize-space": check(name, len(args) <= 1) if args: s = to_string(args[0]) else: s = get_string_value(context.node) s = s.strip() return " ".join(s.split()) elif name == "translate": check(name, len(args) == 3) args = map(to_string, args) args = map(unicode, args) s, a, b = args n = len(b) d = a[n:] a = a[:n] table = {} for c in d: table[ord(c)] = None for i in range(n): c = a[i] if ord(c) not in table: table[ord(c)] = ord(b[i]) return s.translate(table) elif name == "boolean": check(name, len(args) == 1) return to_boolean(args[0]) elif name == "not": check(name, len(args) == 1) return not to_boolean(args[0]) elif name == "true": check(name, not args) return True elif name == "false": check(name, not args) return False elif name == "lang": check(name, len(args) == 1) raise XPathNotImplementedError, 'lang() not supported.' elif name == "number": check(name, len(args) == 1) if args: s = args[0] else: s = get_string_value(context.node) return to_number(s) elif name == "sum": check(name, len(args) == 1 and is_node_set(args[0])) result = 0.0 for value in args[0]: result += to_number(get_string_value(value)) return result elif name == "floor": check(name, len(args) == 1) return floor(to_number(args[0])) elif name == "ceil": check(name, len(args) == 1) return ceil(to_number(args[0])) elif name == "round": check(name, len(args) == 1) return round(to_number(args[0])) else: raise XPathEvaluationError, 'Unknown function %s().' % name def check(name, test): if not test: raise XPathEvaluationError, \ 'Illegal argument list for %s().' % name PKb.h5´ÀxO1O1pdis/xpath/evaluate.pyc;ò gûOEc@s+dZydklZlZWn&ej odklZlZnXdklZlZdk Tdk l Z d„Z d„Z d„Zd„Zd „Zd „Zhd d <d d <d d<dd <dd<dds<=s>=cCs¬t|ƒ}t|ƒ}|o|octt|ƒ}tt|ƒ}x:|D]2}x)|D]!}t |||ƒot SqXqXWqKWt Sn |p|o|o t |}||f\}}nt|ƒoRtt|ƒ}tt|ƒ}x)|D]!}t |||ƒot SqðqðWt Sq¨t|ƒoCtt|ƒ}x)|D]!}t |||ƒot Sq@q@Wt Sq¨t|ƒot |t|ƒ|ƒSq¨nt |||ƒSdS(N(s is_node_setsxs x_is_node_setsys y_is_node_setsmapsget_string_valuesxxsyyscompare2sopsTruesFalsesrelational_transposes is_numbers to_numbers is_strings is_booleans to_boolean(sopsxsys x_is_node_sets y_is_node_setsyysxx((s8build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/evaluate.pyscomparegsD        cCs|ddgjo­t|ƒp t|ƒot|ƒ}t|ƒ}nOt|ƒp t|ƒot|ƒ}t|ƒ}nt|ƒ}t|ƒ}|djo||jSq}||jSn¾|ddddgjo–t|ƒ}t|ƒ}|djo||jSq}|djo||jSq}|djo||jSq}|djo||jSq}tpt ‚ntpt ‚dS(Ns=s!=ss<=s>=( sops is_booleansxsys to_booleans is_numbers to_numbers to_stringsFalsesAssertionError(sopsxsy((s8build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/evaluate.pyscompare2ˆs2           cCsà|djoõt|tiƒoW|i|ƒ\} } gi }|D]'}t || | ƒo||ƒqCqC~} nat|tiƒoG|idjo |} q×|idjott|ƒ} q×f} nf} x |D]}t| ||ƒ} qÞW| SnÛ|djoÁt|tiƒoz|i|ƒ\} } | tjo td‚ng} xK|D]6}t|| | ƒ} | tj o| i | ƒq^q^Wn td‚x |D]}t| ||ƒ} q¬W| Sn |djoòg}xá|D]Ù} t|tiƒo+|i|ƒ\} } t| | | ƒ} ndt|tiƒoJ|idjot| ƒ} q‘|idjot| ƒ} q‘f} nf} x |D]}t| ||ƒ} q˜Wt || ƒ}qêW|Sntd|‚dS( Nsselfsnodestexts attributes,Wildcard attribute references not supported.s3Only name tests supported for attribute references.schilds"%s" axis not supported.(!saxiss isinstances node_testsatomssNameTestsexpandscontextsurisnamesappends_[1]sinput_node_setsxsis_element_nodesnode_setsNodeTypesfilters is_text_nodespredicate_lists predicatesfilter_singleton_nodessNonesXPathNotImplementedErrorsnodesget_attribute_valuesvaluesresults context_nodesget_child_element_nodessget_child_nodessget_child_text_nodessfilter_node_setsjoin_node_sets(sinput_node_setsaxiss node_testspredicate_listscontextsresults_[1]snodes predicates context_nodesnode_setsnamesurisvaluesx((s8build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/evaluate.pysdo_step§sf B         cCsgg}|iƒ}d|_d|_x8|D]0}||_t||ƒo|i |ƒq+q+W|SdS(Ni( sresultscontext_contextsclonescontextssizespositionsnode_setsnodesevaluate_predicates predicatesappend(snode_sets predicatescontext_contextsnodesresultscontext((s8build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/evaluate.pysfilter_singleton_nodesãs    cCs|g}|iƒ}t|ƒ|_d|_xG|D]?}|id7_||_t ||ƒo|i |ƒq1q1W|SdS(Nii( sresultscontext_contextsclonescontextslensnode_setssizespositionsnodesevaluate_predicates predicatesappend(snode_sets predicatescontext_contextsnodesresultscontext((s8build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/evaluate.pysfilter_node_setîs   cCs;|i|ƒ}t|ƒo||ijSn t|ƒSdS(N(s predicatesevaluatescontextsvalues is_numberspositions to_boolean(s predicatescontextsvalue((s8build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/evaluate.pysevaluate_predicateús cCsf |djot|| ƒt|iƒSn7 |djot|| ƒt|iƒSn |djoBt|t|ƒdjot|dƒƒtt|dƒƒSn¼|djo&t|t|ƒdjƒt d‚n‰|dd d gjot|t|ƒdjƒ|oF|d}t|t|ƒƒt|ƒdjod Sn|d}n |i }t |ƒod d f\}}n1t|ƒot|ƒ\}}nt d |‚|djo|Sqb |d jo|Sqb |d jpt‚|o t d ‚qb |SnW|djoCt|t|ƒdjƒ|ot|dƒSqb t|i ƒSn|djo9t|t|ƒdjƒtt|ƒ}d i|ƒSnÁ|djoAt|t|ƒdjƒtt|ƒ}|di|dƒSns|djoGt|t|ƒdjƒtt|ƒ}|di|dƒdjSn|djodt|t|ƒdjƒtt|ƒ}|di|dƒ} | djod Sqb |d| Sn®|djoxt|t|ƒdjƒtt|ƒ}|di|dƒ} | djod Sqb | t|dƒ7} |d| Sn)|djoÎt|t|ƒdjpt|ƒdjƒt|dƒ}ttt|dƒƒƒd} t|ƒdjot| dƒ} || Sqb ttt|dƒƒƒ} | | }t| dƒ} || |!SnN|djoWt|t|ƒdjƒ|ot|dƒ}nt|i ƒ}tt|ƒƒSnê|djoft|t|ƒdjƒ|ot|dƒ}nt|i ƒ}|i ƒ}di|i!ƒƒSnw|djoðt|t|ƒdjƒtt|ƒ}tt"|ƒ}|\}} } t| ƒ}| |}| | } h}x|D]} t)|t*| ƒ # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ Slow but portable XPath tokenizer This intentionally does not use the "re" module. """ from pdis.xpath.xpath_exceptions import XPathParseError from pdis.xpath.atoms import * punctuation = ['(', ')', '[', ']', '.', '..', '@', ',', '::'] relationals = ['=', '!=', '<', '<=', '>', '>='] arithmetic = ['*', '+', '-'] operator_syntax = relationals + arithmetic + ['/', '//', '|'] operator_names = ['and', 'or', 'mod', 'div'] operators = operator_syntax + operator_names node_types = ['comment', 'text', 'processing-instruction', 'node'] axis_names = ['ancestor', 'ancestor-or-self', 'attribute', 'child', 'descendant', 'descendant-or-self', 'following', 'following-sibling', 'namespace', 'parent', 'preceding', 'preceding-sibling', 'self'] class TokenStream: """ Iterable stream of tokens extracted from an XPath expression The returned tokens can be any of the following: * A string in punctuation + operators. * An instance of one of the following: - Number - Literal - NameTest - VariableReference - FunctionName - NodeType - AxisName """ def __init__(self, input_string): self.tokens = split_tokens(input_string) self.position = 0 def __iter__(self): return self def next(self): """ Either return the next token or raise StopIteration. """ if self.position >= len(self.tokens): raise StopIteration token = self.tokens[self.position] self.position += 1 return token def peek(self): """ Return either the token that next() would return next or None. """ if self.position >= len(self.tokens): return None return self.tokens[self.position] def push_back(self, token): """ Push a token returned by next() back onto the stream. """ self.position -= 1 assert self.tokens[self.position] == token def split_tokens(s): """ Split an XPath expression into a list of tokens. """ i = 0 t = None result = [] while True: t, i = scan_token(s, i, t) if t is None: return result result.append(t) _tokens_that_never_precede_an_operator = operators + ['@', '::', '(', '[', ',', None] def scan_token(s, i, preceding_token = None): """ Get the next token starting at position i in the string s. The return value is (t, j) where t is the token and j is the position at which to start scanning for the next token. The returned token can be any of the following: * None, signifying that the end of the input string has been reached. * A string in punctuation + operators. * An instance of one of the following: - Number - Literal - NameTest - VariableReference - FunctionName - NodeType - AxisName """ # This function implements the disambiguation rules defined # in Section 3.7 of the XPath specification. scan_raw_token() # does the work of actually splitting the input into tokens. t, j = scan_raw_token(s, i) if t == '*': if preceding_token in _tokens_that_never_precede_an_operator: t = NameTest('*') if t.__class__ is QName: peek = j while s[peek:peek+1].isspace(): peek += 1 if preceding_token not in _tokens_that_never_precede_an_operator: # "...an NCName must be recognized as an OperatorName" if t.prefix is None and t.local_part in operator_names: t = t.local_part else: raise XPathParseError('Expected an operator name, not "%s".' % t) elif s[peek:peek+1] == '(': # "...the token must be recognized as a NodeType or a FunctionName" if t.prefix is None and t.local_part in node_types: t = NodeType(t.local_part) else: t = FunctionName(t.prefix, t.local_part) elif s[peek:peek+2] == '::': # "...the token must be recognized as an AxisName" if t.prefix is None and t.local_part in axis_names: t = AxisName(t.local_part) else: raise XPathParseError('Expected an axis name, not "%s".' % t) else: # "Otherwise, the token must not be recognized as...an # OperatorName, a NodeType, a FunctionName, or an AxisName." t = NameTest(t.prefix, t.local_part) return (t, j) def _build_punctuation_map(): tokens = punctuation + operator_syntax # Put a after b if a is a prefix of b: tokens.sort() tokens.reverse() map = {} for token in tokens: key = token[0] if key not in map: map[key] = [] map[key].append(token) return map _punctuation_map = _build_punctuation_map() def scan_raw_token(s, i): """ Get the next token starting at position i in the string s. The return value is (t, j) where t is the token and j is the position at which to start scanning for the next token. The returned token can be any of the following: * None, signifying that the end of the input string has been reached. * A string in punctuation + operator_syntax. * An instance of one of the following: - Number - Literal - NameTest - VariableReference - QName """ while s[i:i+1].isspace(): i += 1 if i >= len(s): return (None, i) c = s[i] # Punctuation or operator for t in _punctuation_map.get(c, ()): if s.startswith(t, i): j = i + len(t) if t == '.' and s[j:j+1].isdigit(): pass # Number -- handled below. else: return (t, j) # Literal for quote_char in ['"', "'"]: if c == quote_char: i += 1 j = s.find(quote_char, i) if j < 0: raise XPathParseError('Unmatched quote character.') return (Literal(s[i:j]), j + 1) # Number if c.isdigit() or c == '.': j = i while s[j:j+1].isdigit(): j += 1 if s[j:j+1] == '.': j += 1 while s[j:j+1].isdigit(): j += 1 return (Number(s[i:j]), j) # Variable Reference if c == '$' and ncname_begins(s, i + 1): prefix, name, j = scan_qname(s, i + 1) return (VariableReference(prefix, name), j) # Name Test or QName if ncname_begins(s, i): prefix, name, j = scan_qname(s, i) if prefix is None and s[j:j+2] == ':*': return (NameTest(s[i:j], '*'), j + 2) else: return (QName(prefix, name), j) raise XPathParseError('No valid token here: "%s"' % s[i:]) def scan_qname(s, i): t1, j = scan_ncname(s, i) if s[j:j+1] == ':' and ncname_begins(s, j + 1): t2, j = scan_ncname(s, j + 1) else: t1, t2 = None, t1 return (t1, t2, j) def scan_ncname(s, i): assert ncname_begins(s, i) j = i + 1 while ncname_continues(s, j): j += 1 return (s[i:j], j) def ncname_begins(s, i): # This is only correct to the extent that the behavior of isalpha() # happens to correspond to the XML specification's definition of Letter. c = s[i:i+1] return c.isalpha() or c == '_' def ncname_continues(s, i): # This is only correct to the extent that the behavior of isalnum() # happens to correspond to the XML specification's definition of # Letter | Digit | CombiningChar | Extender. c = s[i:i+1] return c.isalnum() or c in ['.', '-', '_'] PKb.h5‡Aeà%à%pdis/xpath/lexer.pyc;ò gûOEc @s[dZdklZdkTddddddd d d g Zd d ddddgZdddgZeedddgZddddgZeeZ ddddgZ d d!d"d#d$d%d&d'd(d)d*d+d,g Z d-fd.„ƒYZ d/„Z e d d ddd egZed0„Zd1„ZeƒZd2„Zd3„Zd4„Zd5„Zd6„Zd7S(8sU Slow but portable XPath tokenizer This intentionally does not use the "re" module. (sXPathParseError(s*s(s)s[s]s.s..s@s,s::s=s!=ss>=s*s+s-s/s//s|sandsorsmodsdivscommentstextsprocessing-instructionsnodesancestorsancestor-or-selfs attributeschilds descendantsdescendant-or-selfs followingsfollowing-siblings namespacesparents precedingspreceding-siblingsselfs TokenStreamcBs;tZdZd„Zd„Zd„Zd„Zd„ZRS(sc Iterable stream of tokens extracted from an XPath expression The returned tokens can be any of the following: * A string in punctuation + operators. * An instance of one of the following: - Number - Literal - NameTest - VariableReference - FunctionName - NodeType - AxisName cCst|ƒ|_d|_dS(Ni(s split_tokenss input_stringsselfstokenssposition(sselfs input_string((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/lexer.pys__init__CscCs|SdS(N(sself(sself((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/lexer.pys__iter__GscCsJ|it|iƒjo t‚n|i|i}|id7_|SdS(sF Either return the next token or raise StopIteration. iN(sselfspositionslenstokenss StopIterationstoken(sselfstoken((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/lexer.pysnextJs  cCs3|it|iƒjotSn|i|iSdS(sP Return either the token that next() would return next or None. N(sselfspositionslenstokenssNone(sself((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/lexer.pyspeekUscCs1|id8_|i|i|jpt‚dS(sG Push a token returned by next() back onto the stream. iN(sselfspositionstokensstokensAssertionError(sselfstoken((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/lexer.pys push_back^s(s__name__s __module__s__doc__s__init__s__iter__snextspeeks push_back(((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/lexer.pys TokenStream4s    cCs_d}t}g}xFto>t|||ƒ\}}|tjo|Sn|i|ƒqWdS(s: Split an XPath expression into a list of tokens. iN(sisNonestsresultsTrues scan_tokensssappend(sssistsresult((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/lexer.pys split_tokenses cCs»t||ƒ\}}|djo!|tjotdƒ}qCn|it joZ|}x'|||d!i ƒo|d7}q\W|tjoA|i t jo |itjo |i}q©td|ƒ‚q­|||d!djoL|i t jo |itjot|iƒ}q©t|i |iƒ}q­|||d!djoG|i t jo |itjot|iƒ}q©td|ƒ‚q­t|i |iƒ}n||fSdS( s) Get the next token starting at position i in the string s. The return value is (t, j) where t is the token and j is the position at which to start scanning for the next token. The returned token can be any of the following: * None, signifying that the end of the input string has been reached. * A string in punctuation + operators. * An instance of one of the following: - Number - Literal - NameTest - VariableReference - FunctionName - NodeType - AxisName s*is$Expected an operator name, not "%s".s(is::s Expected an axis name, not "%s".N(sscan_raw_tokensssistsjspreceding_tokens&_tokens_that_never_precede_an_operatorsNameTests __class__sQNamespeeksisspacesprefixsNones local_partsoperator_namessXPathParseErrors node_typessNodeTypes FunctionNames axis_namessAxisName(sssispreceding_tokenspeeksjst((s5build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/lexer.pys scan_tokents0       cCsstt}|iƒ|iƒh}xD|D]<}|d}||jog|| # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ Slow but portable XPath parser """ from pdis.xpath.xpath_exceptions import XPathParseError from pdis.xpath.lexer import TokenStream from pdis.xpath.syntax import * def parse_xpath(input_string): return Parser(input_string).parse() class Parser(TokenStream): def parse(self): x = self.parse_expression() t = self.peek() if t is not None: raise XPathParseError, 'Unexpected token after expression: %s' % t return x def next(self): try: return TokenStream.next(self) except StopIteration: raise XPathParseError, 'Unexpected end of token stream.' precedence_table = { 'or' : 1, 'and' : 2, '=' : 3, '!=' : 3, '<' : 4, '>' : 4, '<=' : 4, '>=' : 4, '+' : 5, '-' : 5, '*' : 6, 'div' : 6, 'mod' : 6, '|' : 8 } unary_minus_precedence = 7 def parse_expression(self, left_precedence = 0): if self.peek() != '-': x = self.parse_path_expression() else: if left_precedence > self.unary_minus_precedence: raise XPathParseError, 'Unary minus not allowed here.' else: op = self.next() x = self.parse_expression(self.unary_minus_precedence) x = UnaryOp(op, x) while True: op = self.peek() right_precedence = self.precedence_table.get(op, 0) if left_precedence >= right_precedence: return x else: self.next() y = self.parse_expression(right_precedence) x = BinaryOp(op, x, y) def parse_path_expression(self): t = self.peek() if t == '(' or isinstance(t, (Literal, Number, FunctionName, VariableReference)): x = self.parse_filter_expression() return self.parse_rest_of_path(x) else: return self.parse_location_path() def parse_filter_expression(self): x = self.parse_primary_expression() predicate_list = self.parse_predicate_list() if predicate_list: # XXX This is not as per the XPath specification, because # it results in the nodes returned by the expression being # filtered as singleton node sets, instead of as a single # node set. x = LocationStep(x, "self", NodeType("node"), predicate_list) return x def parse_primary_expression(self): t = self.next() if t == '(': x = self.parse_expression() if self.next() != ')': raise XPathParseError, 'Expected closing parenthesis.' return x elif isinstance(t, (Literal, Number, VariableReference)): return t elif isinstance(t, FunctionName): self.push_back(t) return self.parse_function_call() else: raise XPathParseError, 'Invalid primary expression.' def parse_function_call(self): f = self.next() if not isinstance(f, FunctionName): raise XPathParseError, 'Expected function name.' if self.next() != '(': raise XPathParseError, 'Expected opening parenthesis after function name.' args = [] if self.peek() == ')': self.next() else: while True: args.append(self.parse_expression()) t = self.next() if t == ',': continue elif t == ')': break else: raise XPathParseError, \ 'Expected comma or closing paren after function argument.' return FunctionCall(f, args) def parse_location_path(self): t = self.next() if t == '/': x = Root() t2 = self.peek() if not (isinstance(t2, (NameTest, NodeType, AxisName)) or t2 in ['@', '.', '..']): return x elif t == '//': x = LocationStep(Root(), "descendant-or-self", NodeType("node"), []) else: self.push_back(t) x = None return self.parse_relative_location_path(x) def parse_relative_location_path(self, x): x = self.parse_location_step(x) return self.parse_rest_of_path(x) def parse_rest_of_path(self, x): t = self.peek() if t == '/': self.next() return self.parse_relative_location_path(x) elif t == '//': self.next() x = LocationStep(x, "descendant-or-self", NodeType("node"), []) return self.parse_relative_location_path(x) else: return x def parse_location_step(self, prefix): t = self.next() if isinstance(t, AxisName): if self.next() != '::': raise XPathParseError, 'Expected "::" after axis name.' axis = t.name node_test = self.parse_node_test() predicate_list = self.parse_predicate_list() elif t == '@': axis = "attribute" node_test = self.parse_node_test() predicate_list = self.parse_predicate_list() elif t == '.': axis = "self" node_test = NodeType("node") predicate_list = [] elif t == '..': axis = "parent" node_test = NodeType("node") predicate_list = [] else: self.push_back(t) axis = "child" node_test = self.parse_node_test() predicate_list = self.parse_predicate_list() return LocationStep(prefix, axis, node_test, predicate_list) def parse_node_test(self): f = self.next() if isinstance(f, NameTest): return f elif isinstance(f, NodeType): if self.next() != '(': raise XPathParseError, \ 'Expected opening parenthesis after node type.' t = self.next() if t == ')': return f if isinstance(t, Literal) and self.next() == ')' \ and f.name == "processing-instruction": return t raise XPathParseError, 'Unexpected argument in node type test.' else: raise XPathParseError, 'Invalid node test.' def parse_predicate_list(self): result = [] while self.peek() == '[': self.next() result.append(self.parse_expression()) if self.next() != ']': raise XPathParseError, 'Expected "]".' return result PKb.h5dC(ît!t!pdis/xpath/parser.pyc;ò gûOEc@sJdZdklZdklZdkTd„Zdefd„ƒYZdS(s Slow but portable XPath parser (sXPathParseError(s TokenStream(s*cCst|ƒiƒSdS(N(sParsers input_stringsparse(s input_string((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pys parse_xpath%ssParsercBs tZd„Zd„Zhdd<dd<dd<d d<d d <d d <d d <dd <dd<dd<dd<dd<dd<dd|iƒ}|iƒ}|tj otd|‚n|SdS(Ns%Unexpected token after expression: %s(sselfsparse_expressionsxspeekstsNonesXPathParseError(sselfsxst((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse)s    cCs4yti|ƒSWntj otd‚nXdS(NsUnexpected end of token stream.(s TokenStreamsnextsselfs StopIterationsXPathParseError(sself((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysnext0ssorisandis=is!=ss<=s>=s+is-s*isdivsmods|iiicCsá|iƒdjo|iƒ}nK||ijo td‚n.|iƒ}|i |iƒ}t ||ƒ}xmt oe|iƒ}|i i |dƒ}||jo|Sqp|iƒ|i |ƒ}t|||ƒ}qpWdS(Ns-sUnary minus not allowed here.i(sselfspeeksparse_path_expressionsxsleft_precedencesunary_minus_precedencesXPathParseErrorsnextsopsparse_expressionsUnaryOpsTruesprecedence_tablesgetsright_precedencesysBinaryOp(sselfsleft_precedencesysxsright_precedencesop((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_expressionAs      cCs`|iƒ}|djpt|ttttfƒo|iƒ}|i |ƒSn |i ƒSdS(Ns(( sselfspeeksts isinstancesLiteralsNumbers FunctionNamesVariableReferencesparse_filter_expressionsxsparse_rest_of_pathsparse_location_path(sselfstsx((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_path_expressionVs  ) cCsF|iƒ}|iƒ}|ot|dtdƒ|ƒ}n|SdS(Nsselfsnode(sselfsparse_primary_expressionsxsparse_predicate_listspredicate_lists LocationStepsNodeType(sselfsxspredicate_list((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_filter_expression^s   cCs¦|iƒ}|djo4|iƒ}|iƒdjo td‚n|SnVt|ttt fƒo|Sn5t|t ƒo|i |ƒ|i ƒSn td‚dS(Ns(s)sExpected closing parenthesis.sInvalid primary expression.( sselfsnextstsparse_expressionsxsXPathParseErrors isinstancesLiteralsNumbersVariableReferences FunctionNames push_backsparse_function_call(sselfstsx((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_primary_expressionis     cCsß|iƒ}t|tƒ o td‚n|iƒdjo td‚ng}|iƒdjo|iƒn^xZtoR|i |i ƒƒ|iƒ}|djoqtqt|djoPqttd‚qtWt ||ƒSdS(NsExpected function name.s(s1Expected opening parenthesis after function name.s)s,s8Expected comma or closing paren after function argument.( sselfsnextsfs isinstances FunctionNamesXPathParseErrorsargsspeeksTruesappendsparse_expressionsts FunctionCall(sselfsfsargsst((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_function_callxs$      cCs½|iƒ}|djoQtƒ}|iƒ}t|tt t fƒp|dddgj o|Sq¬nC|djo"t tƒdt dƒgƒ}n|i |ƒt }|i|ƒSdS(Ns/s@s.s..s//sdescendant-or-selfsnode(sselfsnextstsRootsxspeekst2s isinstancesNameTestsNodeTypesAxisNames LocationSteps push_backsNonesparse_relative_location_path(sselfst2stsx((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_location_pathŽs    0  " cCs |i|ƒ}|i|ƒSdS(N(sselfsparse_location_stepsxsparse_rest_of_path(sselfsx((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_relative_location_pathžscCs|iƒ}|djo|iƒ|i|ƒSnH|djo6|iƒt|dtdƒgƒ}|i|ƒSn|SdS(Ns/s//sdescendant-or-selfsnode(sselfspeekstsnextsparse_relative_location_pathsxs LocationStepsNodeType(sselfsxst((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_rest_of_path¢s     cCs$|iƒ}t|tƒoE|iƒdjo td‚n|i}|iƒ}|i ƒ}n­|djo"d}|iƒ}|i ƒ}n~|djod}t dƒ}g}nU|djod }t dƒ}g}n,|i |ƒd }|iƒ}|i ƒ}t||||ƒSdS( Ns::sExpected "::" after axis name.s@s attributes.sselfsnodes..sparentschild(sselfsnextsts isinstancesAxisNamesXPathParseErrorsnamesaxissparse_node_tests node_testsparse_predicate_listspredicate_listsNodeTypes push_backs LocationStepsprefix(sselfsprefixs node_testspredicate_liststsaxis((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_location_step®s0               cCsÊ|iƒ}t|tƒo|Sn£t|tƒo‰|iƒdjo td‚n|iƒ}|djo|Snt|tƒo |iƒdjo |i djo|Sntd‚n td‚dS(Ns(s-Expected opening parenthesis after node type.s)sprocessing-instructions&Unexpected argument in node type test.sInvalid node test.( sselfsnextsfs isinstancesNameTestsNodeTypesXPathParseErrorstsLiteralsname(sselfsfst((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_node_testÊs    3 cCsfg}xU|iƒdjoA|iƒ|i|iƒƒ|iƒdjo td‚q q W|SdS(Ns[s]s Expected "]".(sresultsselfspeeksnextsappendsparse_expressionsXPathParseError(sselfsresult((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysparse_predicate_listÜs (s__name__s __module__sparsesnextsprecedence_tablesunary_minus_precedencesparse_expressionsparse_path_expressionsparse_filter_expressionsparse_primary_expressionsparse_function_callsparse_location_pathsparse_relative_location_pathsparse_rest_of_pathsparse_location_stepsparse_node_testsparse_predicate_list(((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pysParser(s  „         N(s__doc__spdis.xpath.xpath_exceptionssXPathParseErrorspdis.xpath.lexers TokenStreamspdis.xpath.syntaxs parse_xpathsParser(sXPathParseErrors TokenStreams parse_xpathsParser((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/parser.pys?s    PKƒ¢f5£a=L!!pdis/xpath/syntax.py# # pdis.xpath.syntax # # Copyright 2004 Helsinki Institute for Information Technology (HIIT) # and the authors. All rights reserved. # # Authors: Ken Rimey # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ XPath syntax nodes """ from pdis.xpath.atoms import * from pdis.xpath.evaluate import to_number, to_boolean, compare, do_step, do_function_call from pdis.xpath.data_model import is_node_set, join_node_sets from pdis.xpath.xpath_exceptions import XPathNotImplementedError, XPathEvaluationError # # Expression nodes # class UnaryOp: """ Unary expression node op -- operator (a string). right -- child node. The operator is actually always "-". """ def __init__(self, op, right): self.op = op self.right = right def __str__(self): return "(%s %s)" % (self.op, self.right) def evaluate(self, context): assert self.op == '-' return - to_number(self.right.evaluate(context)) class BinaryOp: """ Binary expression node op -- operator (a string). left -- left-hand child node. right -- right-hand child node. """ def __init__(self, op, left, right): self.op = op self.left = left self.right = right def __str__(self): return "(%s %s %s)" % (self.left, self.op, self.right) def evaluate(self, context): if self.op == 'or': if to_boolean(self.left.evaluate(context)): return True return to_boolean(self.right.evaluate(context)) elif self.op == 'and': if not to_boolean(self.left.evaluate(context)): return False return to_boolean(self.right.evaluate(context)) elif self.op in ['=', '!=', '<', '>', '<=', '>=']: return compare(self.op, self.left.evaluate(context), self.right.evaluate(context)) elif self.op in ['+', '-', '*', 'div', 'mod']: x = to_number(self.left.evaluate(context)) y = to_number(self.right.evaluate(context)) if self.op == '+': return x + y elif self.op == '-': return x - y elif self.op == '*': return x * y elif self.op == 'div': return x / y elif self.op == 'mod': z = abs(x) % abs(y) if x >= 0: return z else: return -z else: assert False elif self.op == '|': x = self.left.evaluate(context) y = self.right.evaluate(context) if is_node_set(x) and is_node_set(y): # XXX This is incorrect, because it neither preserves # document order nor removes duplicates. return join_node_sets(x, y) else: raise XPathEvaluationError, "Operands of '|' must be node sets." else: assert False class FunctionCall: """ Function call node function -- FunctionName. argument_list -- list of zero or more nodes. """ def __init__(self, function, argument_list): self.function = function self.argument_list = argument_list def __str__(self): return "%s(%s)" % (self.function, ", ".join(map(str, self.argument_list))) def evaluate(self, context): if self.function.prefix: raise XPathNotImplementedError, \ "Namespace prefixes for function names not implemented." name = self.function.local_part args = [arg.evaluate(context) for arg in self.argument_list] return do_function_call(name, args, context) # # Location path nodes # class Root: """ Node representing the head of an absolute location path """ def __init__(self): pass def __str__(self): return "/" def evaluate(self, context): return [context.get_root()] class LocationStep: """ Node representing a step in a location path prefix -- preceding LocationStep, Root, None, or some other node. axis -- axis name (a string). node_test -- NameTest, NodeType, or Literal. predicate_list -- list of zero or more nodes. A value of None for the prefix indicates that this is the head of a relative location path. A Literal value for the node test represents a parameterized processing-instruction test. """ def __init__(self, prefix, axis, node_test, predicate_list): self.prefix = prefix self.axis = axis self.node_test = node_test self.predicate_list = predicate_list def __str__(self): parts = [] if self.prefix is None: pass elif isinstance(self.prefix, Root): parts.append("/") else: parts.append("%s/" % self.prefix) parts.append("%s::" % self.axis) if isinstance(self.node_test, NodeType): parts.append("%s()" % self.node_test) elif isinstance(self.node_test, Literal): parts.append("processing-instruction(%s)" % self.node_test) else: parts.append("%s" % self.node_test) for predicate in self.predicate_list: parts.append("[%s]" % predicate) return "".join(parts) def evaluate(self, context): if self.prefix == None: node_set = [context.node] else: node_set = self.prefix.evaluate(context) assert is_node_set(node_set) return do_step(node_set, self.axis, self.node_test, self.predicate_list, context) PKb.h5ñ‡h¸?"?"pdis/xpath/syntax.pyc;ò gûOEc@s»dZdkTdklZlZlZlZlZdkl Z l Z dk l Z l Z dfd„ƒYZdfd„ƒYZd fd „ƒYZd fd „ƒYZd fd„ƒYZdS(s XPath syntax nodes (s*(s to_numbers to_booleanscomparesdo_stepsdo_function_call(s is_node_setsjoin_node_sets(sXPathNotImplementedErrorsXPathEvaluationErrorsUnaryOpcBs)tZdZd„Zd„Zd„ZRS(s‚ Unary expression node op -- operator (a string). right -- child node. The operator is actually always "-". cCs||_||_dS(N(sopsselfsright(sselfsopsright((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__init__3s cCsd|i|ifSdS(Ns(%s %s)(sselfsopsright(sself((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__str__7scCs2|idjpt‚t|ii|ƒƒ SdS(Ns-(sselfsopsAssertionErrors to_numbersrightsevaluatescontext(sselfscontext((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pysevaluate:s(s__name__s __module__s__doc__s__init__s__str__sevaluate(((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pysUnaryOp*s   sBinaryOpcBs)tZdZd„Zd„Zd„ZRS(s† Binary expression node op -- operator (a string). left -- left-hand child node. right -- right-hand child node. cCs||_||_||_dS(N(sopsselfsleftsright(sselfsopsleftsright((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__init__Fs  cCsd|i|i|ifSdS(Ns (%s %s %s)(sselfsleftsopsright(sself((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__str__KscCs{|idjo;t|ii|ƒƒotSnt|ii|ƒƒSn-|idjo<t|ii|ƒƒ otSnt|ii|ƒƒSná|iddddddgjo/t |i|ii|ƒ|ii|ƒƒSn|id d d d d gjoöt |ii|ƒƒ}t |ii|ƒƒ}|id jo ||Sqw|id jo ||Sqw|id jo ||Sqw|id jo ||Sqw|id jo4t |ƒt |ƒ}|djo|Sqù| Sqwtpt‚n{|idjo\|ii|ƒ}|ii|ƒ}t|ƒo t|ƒot||ƒSqwtd‚ntpt‚dS(Nsorsands=s!=ss<=s>=s+s-s*sdivsmodis|s"Operands of '|' must be node sets.(sselfsops to_booleansleftsevaluatescontextsTruesrightsFalsescompares to_numbersxsysabsszsAssertionErrors is_node_setsjoin_node_setssXPathEvaluationError(sselfscontextsxsysz((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pysevaluateNsF"       (s__name__s __module__s__doc__s__init__s__str__sevaluate(((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pysBinaryOp>s   s FunctionCallcBs)tZdZd„Zd„Zd„ZRS(sl Function call node function -- FunctionName. argument_list -- list of zero or more nodes. cCs||_||_dS(N(sfunctionsselfs argument_list(sselfsfunctions argument_list((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__init__€s cCs*d|iditt|iƒƒfSdS(Ns%s(%s)s, (sselfsfunctionsjoinsmapsstrs argument_list(sself((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__str__„scCsm|iio td‚n|ii}gi}|iD]}||i |ƒƒq7~}t |||ƒSdS(Ns6Namespace prefixes for function names not implemented.(sselfsfunctionsprefixsXPathNotImplementedErrors local_partsnamesappends_[1]s argument_listsargsevaluatescontextsargssdo_function_call(sselfscontextsnamesargss_[1]sarg((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pysevaluate‡s    3(s__name__s __module__s__doc__s__init__s__str__sevaluate(((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys FunctionCallys   sRootcBs)tZdZd„Zd„Zd„ZRS(sA Node representing the head of an absolute location path cCsdS(N((sself((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__init__—scCsdSdS(Ns/((sself((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__str__šscCs|iƒgSdS(N(scontextsget_root(sselfscontext((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pysevaluates(s__name__s __module__s__doc__s__init__s__str__sevaluate(((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pysRoot“s   s LocationStepcBs)tZdZd„Zd„Zd„ZRS(sÅ Node representing a step in a location path prefix -- preceding LocationStep, Root, None, or some other node. axis -- axis name (a string). node_test -- NameTest, NodeType, or Literal. predicate_list -- list of zero or more nodes. A value of None for the prefix indicates that this is the head of a relative location path. A Literal value for the node test represents a parameterized processing-instruction test. cCs(||_||_||_||_dS(N(sprefixsselfsaxiss node_testspredicate_list(sselfsprefixsaxiss node_testspredicate_list((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__init__­s   cCsg}|itjon9t|itƒo|idƒn|id|iƒ|id|iƒt|it ƒo|id|iƒn@t|it ƒo|id|iƒn|id|iƒx"|i D]}|id|ƒqÚWdi |ƒSdS( Ns/s%s/s%s::s%s()sprocessing-instruction(%s)s%ss[%s]s(spartssselfsprefixsNones isinstancesRootsappendsaxiss node_testsNodeTypesLiteralspredicate_lists predicatesjoin(sselfs predicatesparts((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys__str__³s  cCsi|itjo|ig}n'|ii|ƒ}t|ƒpt‚t ||i |i |i |ƒSdS(N( sselfsprefixsNonescontextsnodesnode_setsevaluates is_node_setsAssertionErrorsdo_stepsaxiss node_testspredicate_list(sselfscontextsnode_set((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pysevaluateËs (s__name__s __module__s__doc__s__init__s__str__sevaluate(((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys LocationStep s   N(s__doc__spdis.xpath.atomsspdis.xpath.evaluates to_numbers to_booleanscomparesdo_stepsdo_function_callspdis.xpath.data_models is_node_setsjoin_node_setsspdis.xpath.xpath_exceptionssXPathNotImplementedErrorsXPathEvaluationErrorsUnaryOpsBinaryOps FunctionCallsRoots LocationStep(scompares LocationSteps to_booleansRootsdo_stepsdo_function_callsXPathNotImplementedErrorsXPathEvaluationErrors to_numbers is_node_sets FunctionCallsBinaryOpsjoin_node_setssUnaryOp((s6build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/syntax.pys?s%; PKƒ¢f5Ó^ï»ÉÉpdis/xpath/xpath_exceptions.py# # pdis.xpath.xpath_exceptions # # Copyright 2004 Helsinki Institute for Information Technology (HIIT) # and the authors. All rights reserved. # # Authors: Ken Rimey # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ Exception classes for the xpath package """ class XPathError(Exception): pass class XPathParseError(XPathError): pass class XPathEvaluationError(XPathError): pass class XPathNotImplementedError(XPathError): pass PKb.h5.ü&22pdis/xpath/xpath_exceptions.pyc;ò gûOEc@sbdZdefd„ƒYZdefd„ƒYZdefd„ƒYZdefd„ƒYZd S( s) Exception classes for the xpath package s XPathErrorcBstZRS(N(s__name__s __module__(((s@build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/xpath_exceptions.pys XPathError!ssXPathParseErrorcBstZRS(N(s__name__s __module__(((s@build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/xpath_exceptions.pysXPathParseError$ssXPathEvaluationErrorcBstZRS(N(s__name__s __module__(((s@build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/xpath_exceptions.pysXPathEvaluationError'ssXPathNotImplementedErrorcBstZRS(N(s__name__s __module__(((s@build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/xpath_exceptions.pysXPathNotImplementedError*sN(s__doc__s Exceptions XPathErrorsXPathParseErrorsXPathEvaluationErrorsXPathNotImplementedError(sXPathParseErrorsXPathNotImplementedErrorsXPathEvaluationErrors XPathError((s@build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/xpath_exceptions.pys?sPK9+h5pdis/xpath/tests/__init__.pyPKb.h5`º`ŽŽpdis/xpath/tests/__init__.pyc;ò ÎÌQEc@sdS(N((((s>build/bdist.darwin-8.8.1-i386/egg/pdis/xpath/tests/__init__.pys?sPK(ªf5ÔÖ¥¹ÿÿ!pdis/xpath/tests/test_evaluate.py# # pdis.xpath.test # # Copyright 2004 Helsinki Institute for Information Technology (HIIT) # and the authors. All rights reserved. # # Authors: Ken Rimey , Duncan McGreggor # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. try: from pdis.lib.element import tostring as element_to_string except ImportError: from elementtree.ElementTree import tostring as element_to_string from pdis.xpath import evaluate def tostring(x): if isinstance(x, (str, unicode)): return x elif isinstance(x, tuple): return "<>" else: return element_to_string(x) def test_evaluate(path, document): """ >>> test_evaluate("/", "") ['<>'] >>> test_evaluate("/*", "") [''] >>> test_evaluate("/foo", "") [''] >>> test_evaluate("/bar", "") [] >>> test_evaluate("/foo/two/text()", "123") ['2'] >>> test_evaluate("/foo/two/text()", "123") ['1', '2', '3'] >>> test_evaluate("/foo/two/text()", "1") [] >>> test_evaluate("/foo", "") [''] >>> test_evaluate("/bar", "") [] >>> test_evaluate("/foo/two/text()", "123") ['2'] >>> test_evaluate("/foo/two/text()", "123") ['1', '2', '3'] >>> test_evaluate("/foo/two/text()", "1") [] >>> test_evaluate("/*/*/@color", "") ['red', 'blue'] >>> test_evaluate("/*/*/@color", "") ['red'] >>> test_evaluate("/*/*[@color='red']", "123") ['2'] >>> test_evaluate("/*/*[@color=/*/key]", "red123") ['2'] >>> test_evaluate("/*/*[@color[.='red']]", "123") ['2'] >>> test_evaluate("/*/*[2]", "123") ['2'] >>> test_evaluate("/*/*", "1234567") ['23', '45', '67'] >>> test_evaluate("/*/text()", "1234567") ['1', '3', '5', '7'] >>> test_evaluate("/*/node()", "1234567") ['1', '23', '3', '45', '5', '67', '7'] >>> test_evaluate("/*/* | /*/text()", "1234567") ['23', '45', '67', '1', '3', '5', '7'] >>> test_evaluate("/*/* | /*/text()", "1234567") ['23', '45', '67', '1', '3', '5', '7'] >>> test_evaluate("(/*/one | /*/two)/@color", "") ['red', 'green'] >>> test_evaluate("/*/*[position() = last()]", "123") ['3'] >>> test_evaluate("count(/*/*)", "123") 3.0 >>> test_evaluate("local-name(/*/*[text() = 1])", "123") one >>> test_evaluate("namespace-uri(/*/*[text() = 2])", "123") blah >>> test_evaluate("name(/*/*[text() = 3])", "123") three >>> test_evaluate("string(2 + 2 = 4)", "") true >>> test_evaluate("concat(/*/one, '-', /*/*[last()])", "123") 1-3 >>> test_evaluate("/*/*[starts-with(., 'up')]", "Onceupona time.") ['upon'] >>> test_evaluate("/*/*[contains(., 'e')]", "Onceupona time.") ['Once', 'a time.'] >>> test_evaluate('substring-before("1999/04/01", "/")', '') 1999 >>> test_evaluate('substring-after("1999/04/01", "19")', '') 99/04/01 >>> test_evaluate("substring('12345', 1.5, 2.6)", "") 234 >>> test_evaluate("substring('12345', 0, 3)", "") 12 >>> test_evaluate("translate('---aaa---', 'abc-', 'ABC')", "") AAA >>> test_evaluate("boolean(3.2)", "") True >>> test_evaluate("not(true())", "") False >>> test_evaluate("not(false())", "") True >>> test_evaluate("number(' 03.14 ')", "") 3.14 >>> test_evaluate("sum(/*/*)", "110100") 111.0 >>> test_evaluate("concat(floor(3.5), ceil(3.5), round(3.5))", "") 344 """ result = evaluate(path, document) if isinstance(result, list): result = map(tostring, result) print result def _test(): import doctest doctest.testmod() if __name__ == "__main__": _test() PKb.h5êWÓ{%%"pdis/xpath/tests/test_evaluate.pyc;ò ÍPEc@sxydklZWn ej odklZnXdklZd„Zd„Zd„Ze djo eƒndS((stostring(sevaluatecCsDt|ttfƒo|Sn#t|tƒodSn t|ƒSdS(Ns <>(s isinstancesxsstrsunicodestupleselement_to_string(sx((sCbuild/bdist.darwin-8.8.1-i386/egg/pdis/xpath/tests/test_evaluate.pystostring$s cCs;t||ƒ}t|tƒott|ƒ}n|GHdS(s† >>> test_evaluate("/", "") ['<>'] >>> test_evaluate("/*", "") [''] >>> test_evaluate("/foo", "") [''] >>> test_evaluate("/bar", "") [] >>> test_evaluate("/foo/two/text()", "123") ['2'] >>> test_evaluate("/foo/two/text()", "123") ['1', '2', '3'] >>> test_evaluate("/foo/two/text()", "1") [] >>> test_evaluate("/foo", "") [''] >>> test_evaluate("/bar", "") [] >>> test_evaluate("/foo/two/text()", "123") ['2'] >>> test_evaluate("/foo/two/text()", "123") ['1', '2', '3'] >>> test_evaluate("/foo/two/text()", "1") [] >>> test_evaluate("/*/*/@color", "") ['red', 'blue'] >>> test_evaluate("/*/*/@color", "") ['red'] >>> test_evaluate("/*/*[@color='red']", "123") ['2'] >>> test_evaluate("/*/*[@color=/*/key]", "red123") ['2'] >>> test_evaluate("/*/*[@color[.='red']]", "123") ['2'] >>> test_evaluate("/*/*[2]", "123") ['2'] >>> test_evaluate("/*/*", "1234567") ['23', '45', '67'] >>> test_evaluate("/*/text()", "1234567") ['1', '3', '5', '7'] >>> test_evaluate("/*/node()", "1234567") ['1', '23', '3', '45', '5', '67', '7'] >>> test_evaluate("/*/* | /*/text()", "1234567") ['23', '45', '67', '1', '3', '5', '7'] >>> test_evaluate("/*/* | /*/text()", "1234567") ['23', '45', '67', '1', '3', '5', '7'] >>> test_evaluate("(/*/one | /*/two)/@color", "") ['red', 'green'] >>> test_evaluate("/*/*[position() = last()]", "123") ['3'] >>> test_evaluate("count(/*/*)", "123") 3.0 >>> test_evaluate("local-name(/*/*[text() = 1])", "123") one >>> test_evaluate("namespace-uri(/*/*[text() = 2])", "123") blah >>> test_evaluate("name(/*/*[text() = 3])", "123") three >>> test_evaluate("string(2 + 2 = 4)", "") true >>> test_evaluate("concat(/*/one, '-', /*/*[last()])", "123") 1-3 >>> test_evaluate("/*/*[starts-with(., 'up')]", "Onceupona time.") ['upon'] >>> test_evaluate("/*/*[contains(., 'e')]", "Onceupona time.") ['Once', 'a time.'] >>> test_evaluate('substring-before("1999/04/01", "/")', '') 1999 >>> test_evaluate('substring-after("1999/04/01", "19")', '') 99/04/01 >>> test_evaluate("substring('12345', 1.5, 2.6)", "") 234 >>> test_evaluate("substring('12345', 0, 3)", "") 12 >>> test_evaluate("translate('---aaa---', 'abc-', 'ABC')", "") AAA >>> test_evaluate("boolean(3.2)", "") True >>> test_evaluate("not(true())", "") False >>> test_evaluate("not(false())", "") True >>> test_evaluate("number(' 03.14 ')", "") 3.14 >>> test_evaluate("sum(/*/*)", "110100") 111.0 >>> test_evaluate("concat(floor(3.5), ceil(3.5), round(3.5))", "") 344 N(sevaluatespathsdocumentsresults isinstanceslistsmapstostring(spathsdocumentsresult((sCbuild/bdist.darwin-8.8.1-i386/egg/pdis/xpath/tests/test_evaluate.pys test_evaluate,s ZcCsdk}|iƒdS(N(sdocteststestmod(sdoctest((sCbuild/bdist.darwin-8.8.1-i386/egg/pdis/xpath/tests/test_evaluate.pys_testŒs s__main__N( spdis.lib.elementstostringselement_to_strings ImportErrorselementtree.ElementTrees pdis.xpathsevaluates test_evaluates_tests__name__(sevaluates_teststostringselement_to_strings test_evaluate((sCbuild/bdist.darwin-8.8.1-i386/egg/pdis/xpath/tests/test_evaluate.pys?s   `  PKù¥f5Ž‘tC99pdis/xpath/tests/test_parser.py# # pdis.xpath.test_parser # # Copyright 2004 Helsinki Institute for Information Technology (HIIT) # and the authors. All rights reserved. # # Authors: Ken Rimey , Duncan McGreggor # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. def test_parser(): """ >>> from pdis.xpath.parser import parse_xpath as parse >>> print parse("/") / >>> print parse("foo") child::foo >>> print parse("/foo") /child::foo >>> print parse("//foo") /descendant-or-self::node()/child::foo >>> print parse("foo/bar") child::foo/child::bar >>> print parse("/foo/bar") /child::foo/child::bar >>> print parse("child::foo") child::foo >>> print parse("@foo") attribute::foo >>> print parse(".") self::node() >>> print parse("..") parent::node() >>> print parse("foo[one]") child::foo[child::one] >>> print parse("foo[one][two]") child::foo[child::one][child::two] >>> print parse("node()") child::node() >>> print parse("processing-instruction()") child::processing-instruction() >>> print parse("processing-instruction('whatever')") child::processing-instruction("whatever") >>> print parse("'foo'") "foo" >>> print parse("3.14") 3.14 >>> print parse("(3.14)") 3.14 >>> print parse("$work") $work >>> print parse("f()") f() >>> print parse("f(1)") f(1.0) >>> print parse("f(1, 2)") f(1.0, 2.0) >>> print parse("f()/blah") f()/child::blah >>> print parse("f()[maybe]") f()/self::node()[child::maybe] >>> print parse("f()[maybe]/blah") f()/self::node()[child::maybe]/child::blah >>> print parse("1 + 2 + 3 + 4 + 5") ((((1.0 + 2.0) + 3.0) + 4.0) + 5.0) >>> print parse("0 or 1 and 2 = 3 < 4 + 5 * 6 | 8") (0.0 or (1.0 and (2.0 = (3.0 < (4.0 + (5.0 * (6.0 | 8.0))))))) >>> print parse("1 + 2 * 3 | 4 * 5 + 6") ((1.0 + ((2.0 * (3.0 | 4.0)) * 5.0)) + 6.0) >>> print parse("1 | 2 * 3 + 4 * 5 | 6") (((1.0 | 2.0) * 3.0) + (4.0 * (5.0 | 6.0))) >>> print parse("1 * (2 + 3)") (1.0 * (2.0 + 3.0)) >>> print parse("f() + f(1) + f(1, 2) + f(1, 2, 3)") (((f() + f(1.0)) + f(1.0, 2.0)) + f(1.0, 2.0, 3.0)) >>> print parse("f(1 + 2, f(2, 3))") f((1.0 + 2.0), f(2.0, 3.0)) >>> print parse("foo[1 + 2 = 3]") child::foo[((1.0 + 2.0) = 3.0)] >>> print parse("item[color = 'blue']") child::item[(child::color = "blue")] >>> print parse("1 * -2 * --3 * ---4") (((1.0 * (- 2.0)) * (- (- 3.0))) * (- (- (- 4.0)))) >>> print parse("-1-2--3---4") ((((- 1.0) - 2.0) - (- 3.0)) - (- (- 4.0))) >>> print parse("-1 * -2|3 * -2|3|4") (((- 1.0) * (- (2.0 | 3.0))) * (- ((2.0 | 3.0) | 4.0))) """ def _test(): import doctest doctest.testmod() if __name__ == "__main__": _test() PKb.h5.3Å- - pdis/xpath/tests/test_parser.pyc;ò çPEc@s.d„Zd„Zedjo eƒndS(cCsdS(s¼ >>> from pdis.xpath.parser import parse_xpath as parse >>> print parse("/") / >>> print parse("foo") child::foo >>> print parse("/foo") /child::foo >>> print parse("//foo") /descendant-or-self::node()/child::foo >>> print parse("foo/bar") child::foo/child::bar >>> print parse("/foo/bar") /child::foo/child::bar >>> print parse("child::foo") child::foo >>> print parse("@foo") attribute::foo >>> print parse(".") self::node() >>> print parse("..") parent::node() >>> print parse("foo[one]") child::foo[child::one] >>> print parse("foo[one][two]") child::foo[child::one][child::two] >>> print parse("node()") child::node() >>> print parse("processing-instruction()") child::processing-instruction() >>> print parse("processing-instruction('whatever')") child::processing-instruction("whatever") >>> print parse("'foo'") "foo" >>> print parse("3.14") 3.14 >>> print parse("(3.14)") 3.14 >>> print parse("$work") $work >>> print parse("f()") f() >>> print parse("f(1)") f(1.0) >>> print parse("f(1, 2)") f(1.0, 2.0) >>> print parse("f()/blah") f()/child::blah >>> print parse("f()[maybe]") f()/self::node()[child::maybe] >>> print parse("f()[maybe]/blah") f()/self::node()[child::maybe]/child::blah >>> print parse("1 + 2 + 3 + 4 + 5") ((((1.0 + 2.0) + 3.0) + 4.0) + 5.0) >>> print parse("0 or 1 and 2 = 3 < 4 + 5 * 6 | 8") (0.0 or (1.0 and (2.0 = (3.0 < (4.0 + (5.0 * (6.0 | 8.0))))))) >>> print parse("1 + 2 * 3 | 4 * 5 + 6") ((1.0 + ((2.0 * (3.0 | 4.0)) * 5.0)) + 6.0) >>> print parse("1 | 2 * 3 + 4 * 5 | 6") (((1.0 | 2.0) * 3.0) + (4.0 * (5.0 | 6.0))) >>> print parse("1 * (2 + 3)") (1.0 * (2.0 + 3.0)) >>> print parse("f() + f(1) + f(1, 2) + f(1, 2, 3)") (((f() + f(1.0)) + f(1.0, 2.0)) + f(1.0, 2.0, 3.0)) >>> print parse("f(1 + 2, f(2, 3))") f((1.0 + 2.0), f(2.0, 3.0)) >>> print parse("foo[1 + 2 = 3]") child::foo[((1.0 + 2.0) = 3.0)] >>> print parse("item[color = 'blue']") child::item[(child::color = "blue")] >>> print parse("1 * -2 * --3 * ---4") (((1.0 * (- 2.0)) * (- (- 3.0))) * (- (- (- 4.0)))) >>> print parse("-1-2--3---4") ((((- 1.0) - 2.0) - (- 3.0)) - (- (- 4.0))) >>> print parse("-1 * -2|3 * -2|3|4") (((- 1.0) * (- (2.0 | 3.0))) * (- ((2.0 | 3.0) | 4.0))) N((((sAbuild/bdist.darwin-8.8.1-i386/egg/pdis/xpath/tests/test_parser.pys test_parsersVcCsdk}|iƒdS(N(sdocteststestmod(sdoctest((sAbuild/bdist.darwin-8.8.1-i386/egg/pdis/xpath/tests/test_parser.pys_testus s__main__N(s test_parsers_tests__name__(s test_parsers_test((sAbuild/bdist.darwin-8.8.1-i386/egg/pdis/xpath/tests/test_parser.pys?s X  PKb.h5“×2¤EGG-INFO/dependency_links.txtPKb.h5Du(¤<EGG-INFO/namespace_packages.txtPKb.h5ÎÛROBB¤~EGG-INFO/PKG-INFOPKb.h5NÔ­ ¤ïEGG-INFO/requires.txtPKb.h5Æ(|__¤-EGG-INFO/SOURCES.txtPKb.h5Du(¤¾EGG-INFO/top_level.txtPKb.h5“×2¤÷EGG-INFO/zip-safePKD£f5(åØ88¤'pdis/__init__.pyPKb.h5 Ü?ÀÙÙ¤pdis/__init__.pycPKƒ¢f5ëšÊ" " ¤•pdis/xpath/__init__.pyPKb.h5¶ÅÔn ¤ëpdis/xpath/__init__.pycPKƒ¢f5ë¤6˜˜¤@pdis/xpath/atoms.pyPKb.h5ã,v£((¤ .pdis/xpath/atoms.pycPKƒ¢f5^kÊ2ÊʤcEpdis/xpath/bench.pyPKb.h5_nGó¤^Mpdis/xpath/bench.pycPKƒ¢f5w«Ò‰‰¤–Rpdis/xpath/context.pyPKb.h5< ‰]XX¤RZpdis/xpath/context.pycPKƒ¢f5Ý¡™_EE¤Þ_pdis/xpath/data_model.pyPKb.h5þƒCȤYupdis/xpath/data_model.pycPKƒ¢f5Aóx7474¤˜pdis/xpath/evaluate.pyPKb.h5´ÀxO1O1¤Âpdis/xpath/evaluate.pycPKƒ¢f5‰pŒû-#-#¤‡ópdis/xpath/lexer.pyPKb.h5‡Aeà%à%¤åpdis/xpath/lexer.pycPKƒ¢f5Ž€š¤÷<pdis/xpath/parser.pyPKb.h5dC(ît!t!¤A\pdis/xpath/parser.pycPKƒ¢f5£a=L!!¤è}pdis/xpath/syntax.pyPKb.h5ñ‡h¸?"?"¤;˜pdis/xpath/syntax.pycPKƒ¢f5Ó^ï»Éɤ­ºpdis/xpath/xpath_exceptions.pyPKb.h5.ü&22¤²Àpdis/xpath/xpath_exceptions.pycPK9+h5¤!Æpdis/xpath/tests/__init__.pyPKb.h5`º`ŽŽ¤[Æpdis/xpath/tests/__init__.pycPK(ªf5ÔÖ¥¹ÿÿ!¤$Çpdis/xpath/tests/test_evaluate.pyPKb.h5êWÓ{%%"¤bàpdis/xpath/tests/test_evaluate.pycPKù¥f5Ž‘tC99¤Ç÷pdis/xpath/tests/test_parser.pyPKb.h5.3Å- - ¤=pdis/xpath/tests/test_parser.pycPK##} ¨