示例#1
0
 def evaluate(self, expr):
     """
     The main entry point for evaluating an XPath expression, using self as context
     expr - a unicode object with the XPath expression
     """
     parsed = parser.parse(expr)
     return parsed.evaluate(self)
示例#2
0
文件: util.py 项目: mredar/amara
    def check_xpath(self, test, node):
        '''
        The XPath check is reminiscent of the XSLT pattern check.
        If any ancestor of the node can be used as context for the test XPath,
        such that the node is in the resulting node set, the test succeeds
        '''
        #FIXME: optimize, at least for the simple node test case.  No need to climb all the way up the tree for that
        #for i, t in enumerate(obj.test):
        #FIXME: add support for python callable tests
        #    if isinstance(t, basestring):
        #        obj.test[i:i+1] = []

        if test not in self.cached_xpath:
            self.cached_xpath[test] = parser.parse(test)
        test = self.cached_xpath[test]
        #if hasattr(test, 'evaluate'):
        #if isinstance(test, unicode):
        cnode = node
        while cnode.xml_parent is not None:
            if node in test.evaluate(
                    context(cnode.xml_parent,
                            namespaces=cnode.xml_parent.xml_namespaces)):
                return True
            cnode = cnode.xml_parent
        return False
示例#3
0
 def evaluate(self, expr):
     """
     The main entry point for evaluating an XPath expression, using self as context
     expr - a unicode object with the XPath expression
     """
     parsed = parser.parse(expr)
     return parsed.evaluate(self)
示例#4
0
 def _add(self, xpath, xpath_handler):
     nfa = to_nfa(xpath_parser.parse(xpath), self.namespaces)
     i = len(self.expressions)
     nfa.add_handler((i, xpath_handler))
     exp = Expression(i, xpath, nfa)
     self.expressions.append(exp)
     return exp
示例#5
0
 def _add(self, xpath, xpath_handler):
     nfa = to_nfa(xpath_parser.parse(xpath), self.namespaces)
     i = len(self.expressions)
     nfa.add_handler((i, xpath_handler))
     exp = Expression(i, xpath, nfa)
     self.expressions.append(exp)
     return exp
示例#6
0
def _run_parser_pass(test_cases):
    for args, expected, ctx in test_cases:
        result = parse(*args).evaluate(ctx)
        if hasattr(expected, "isnan") and expected.isnan():
            assert result.isnan()
            continue
        if isinstance(expected, list):
            # convert nodesets to lists to prevent XPath-style nodeset compares
            result = list(result)
            expected = list(expected)
        assert result == expected, (args, result, expected)
示例#7
0
文件: util.py 项目: abed-hawa/amara
 def check_xpath(self, test, node):
     '''
     The XPath check is reminiscent of the XSLT pattern check.
     If any ancestor of the node can be used as context for the test XPath,
     such that the node is in the resulting node set, the test succeeds
     '''
     #FIXME: optimize, at least for the simple node test case.  No need to climb all the way up the tree for that
     #for i, t in enumerate(obj.test):
         #FIXME: add support for python callable tests
     #    if isinstance(t, basestring):
     #        obj.test[i:i+1] = []
     
     if test not in self.cached_xpath:
         self.cached_xpath[test] = parser.parse(test)
     test = self.cached_xpath[test]
     #if hasattr(test, 'evaluate'):
     #if isinstance(test, unicode):
     cnode = node
     while cnode.xml_parent is not None:
         if node in test.evaluate(context(cnode.xml_parent, namespaces=cnode.xml_parent.xml_namespaces)):
             return True
         cnode = cnode.xml_parent
     return False
示例#8
0
    def setup_model(self, parent=None):
        '''
        Process an examplotron document for constraints
        '''
        NSS = {u'ak': AKARA_NAMESPACE, u'eg': EG_NAMESPACE}
        parent = parent if parent is not None else self.model_document
        allowed_elements_test = []
        if isinstance(parent, tree.element):
            #for a in parent.xml_attributes:
            #FIXME: Hack until this issue is fixed: http://trac.xml3k.org/ticket/8
            for a in dict(parent.xml_attributes.items()):
                if a[0] not in [EG_NAMESPACE, AKARA_NAMESPACE]:
                    parent.xml_model.attribute_types[a] = (self.model_document.xml_new_pname_mapping(a[0], a[1], iselement=False, update_class=False), None)
        for e in parent.xml_elements:
            #Constraint info
            eg_occurs = e.xml_attributes.get((EG_NAMESPACE, 'occurs'))
            if not (e.xml_namespace, e.xml_local) in parent.xml_model.element_types:
                parent.xml_model.element_types[e.xml_namespace, e.xml_local] = (self.model_document.xml_new_pname_mapping(e.xml_namespace, e.xml_local, update_class=False), None)
            if not eg_occurs in [u'?', u'*']:
                c = child_element_constraint(e.xml_namespace, e.xml_local)
                parent.xml_model.add_constraint(c)
            if not eg_occurs in [u'+', u'*']:
                parent.xml_model.add_constraint(
                    constraint(u'count(%s) = 1'%named_node_test(e.xml_namespace, e.xml_local, parent), msg=u'Only one instance of element allowed')
                )
            allowed_elements_test.append(named_node_test(e.xml_namespace, e.xml_local, parent))

            #Metadata extraction cues
            #FIXME: Compile these XPath expressions
            mod = e.xml_model
            rattr = e.xml_select(u'@ak:resource', NSS)
            if rattr:
                #ak:resource="" should default to a generated ID
                mod.metadata_resource_expr = rattr[0].xml_value or NODE_ID_MARKER
            #rattr = e.xml_select(u'string(@ak:resource)', NSS)
            #if rattr: mod.metadata_resource_expr = rattr
            relattr = e.xml_select(u'@ak:rel', NSS)
            if relattr:
                if relattr[0].xml_value:
                    mod.metadata_rel_expr = parser.parse(relattr[0].xml_value)
                else:
                    mod.metadata_rel_expr = parser.parse(u'local-name()')
            valattr = e.xml_select(u'@ak:value', NSS)
            if valattr:
                if valattr[0].xml_value:
                    mod.metadata_value_expr = parser.parse(valattr[0].xml_value)
                else:
                    mod.metadata_value_expr = parser.parse(u'.')
            context_attr = e.xml_select(u'@ak:context', NSS)
            if context_attr:
                mod.metadata_context_expr = parser.parse(context_attr[0].xml_value)
            else:
                #If it doesn't state context, don't check context
                mod.metadata_context_expr = None
                #mod.metadata_context_expr = node_test(parent, e, 'parent')

            #Apply default relationship or value expression
            #If there's ak:rel but no ak:value or ak:resource, ak:value=u'.'
            #If there's ak:value but no ak:rel or ak:resource, ak:rel=u'local-name()'
            if mod.metadata_resource_expr:
                if (mod.metadata_value_expr
                    and not mod.metadata_rel_expr):
                    mod.metadata_rel_expr = parser.parse(u'local-name()')
            else:
                if (mod.metadata_rel_expr
                    and not mod.metadata_value_expr):
                    mod.metadata_value_expr = parser.parse(u'.')
                elif (mod.metadata_value_expr
                    and not mod.metadata_rel_expr):
                    mod.metadata_rel_expr = parser.parse(u'local-name()')

            if mod.metadata_resource_expr not in (NODE_ID_MARKER, None):
                if not isinstance(mod.metadata_resource_expr, expressions.expression): mod.metadata_resource_expr = parser.parse(mod.metadata_resource_expr)
            #if mod.metadata_rel_expr is not None:
            #    mod.metadata_rel_expr = parser.parse(mod.metadata_rel_expr)
            #if mod.metadata_value_expr is not None:
            #    mod.metadata_value_expr = parser.parse(mod.metadata_value_expr)
            relelem = e.xml_select(u'ak:rel', NSS)
            
            for rel in relelem:
                mod.other_rel_exprs.append((unicode(rel.name),unicode(rel.value)))
            #print e.xml_name, (mod.metadata_resource_expr, mod.metadata_rel_expr, mod.metadata_value_expr)
            
            #Recurse to process children
            self.setup_model(e)

        if allowed_elements_test:
            parent.xml_model.add_constraint(
                constraint(u'count(%s) = count(*)'%u'|'.join(allowed_elements_test), msg=u'Unexpected elements present')
            )
        else:
            parent.xml_model.add_constraint(
                constraint(u'not(*)', msg=u'Element expected to be empty')
            )