Esempio n. 1
0
class XsdFieldSelector(XsdSelector):
    """Class for defining an XPath field selector for an XSD identity constraint."""
    _ADMITTED_TAGS = {XSD_FIELD}
    pattern = translate_pattern(
        r"(\.//)?((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)/)*((((child::)?"
        r"((\i\c*:)?(\i\c*|\*)))|\.)|((attribute::|@)((\i\c*:)?(\i\c*|\*))))"
        r"(\|(\.//)?((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)/)*"
        r"((((child::)?((\i\c*:)?(\i\c*|\*)))|\.)|"
        r"((attribute::|@)((\i\c*:)?(\i\c*|\*)))))*",
        back_references=False,
        lazy_quantifiers=False,
        anchors=False)
Esempio n. 2
0
 def _parse_value(self, elem):
     try:
         python_pattern = translate_pattern(pattern=elem.attrib['value'],
                                            xsd_version=self.xsd_version,
                                            back_references=False,
                                            lazy_quantifiers=False,
                                            anchors=False)
         return re.compile(python_pattern)
     except KeyError:
         self.parse_error("missing 'value' attribute", elem)
         return re.compile(r'^.*$')
     except (RegexError, re.error, XMLSchemaDecodeError) as err:
         self.parse_error(err, elem)
         return re.compile(r'^.*$')
Esempio n. 3
0
class XsdSelector(XsdComponent):
    """Class for defining an XPath selector for an XSD identity constraint."""
    _ADMITTED_TAGS = {XSD_SELECTOR}
    xpath_default_namespace = ''
    pattern = translate_pattern(
        r"(\.//)?(((child::)?((\i\c*:)?(\i\c*|\*)))|\.)(/(((child::)?"
        r"((\i\c*:)?(\i\c*|\*)))|\.))*(\|(\.//)?(((child::)?((\i\c*:)?"
        r"(\i\c*|\*)))|\.)(/(((child::)?((\i\c*:)?(\i\c*|\*)))|\.))*)*",
        back_references=False,
        lazy_quantifiers=False,
        anchors=False)
    token = None
    parser = None

    def __init__(self, elem, schema, parent):
        super(XsdSelector, self).__init__(elem, schema, parent)

    def _parse(self):
        super(XsdSelector, self)._parse()
        try:
            self.path = self.elem.attrib['xpath']
        except KeyError:
            self.parse_error("'xpath' attribute required")
            self.path = '*'
        else:
            try:
                match = self.pattern.match(self.path.replace(' ', ''))
            except AttributeError:
                # Compile regex pattern
                self.__class__.pattern = re.compile(self.pattern)
                match = self.pattern.match(self.path.replace(' ', ''))

            if not match:
                msg = "invalid XPath expression for an {}"
                self.parse_error(msg.format(self.__class__.__name__))

        # XSD 1.1 xpathDefaultNamespace attribute
        if self.schema.XSD_VERSION > '1.0':
            if 'xpathDefaultNamespace' in self.elem.attrib:
                self.xpath_default_namespace = self._parse_xpath_default_namespace(
                    self.elem)
            else:
                self.xpath_default_namespace = self.schema.xpath_default_namespace

        self.parser = IdentityXPathParser(
            namespaces=self.namespaces,
            strict=False,
            compatibility_mode=True,
            default_namespace=self.xpath_default_namespace,
        )

        try:
            self.token = self.parser.parse(self.path)
        except ElementPathError as err:
            self.token = self.parser.parse('*')
            self.parse_error(err)

    def __repr__(self):
        return '%s(path=%r)' % (self.__class__.__name__, self.path)

    @property
    def built(self):
        return self.token is not None

    @property
    def target_namespace(self):
        # TODO: implement a property in elementpath for getting XPath token's namespace
        if self.token is None:
            pass  # xpathDefaultNamespace="##targetNamespace"
        elif self.token.symbol == ':':
            return self.token[1].namespace or self.xpath_default_namespace
        elif self.token.symbol == '@' and self.token[0].symbol == ':':
            return self.token[0][1].namespace or self.xpath_default_namespace
        return self.schema.target_namespace
Esempio n. 4
0
class XsdSelector(XsdComponent):
    """Class for defining an XPath selector for an XSD identity constraint."""
    _ADMITTED_TAGS = {XSD_SELECTOR}
    xpath_default_namespace = ''
    pattern = translate_pattern(
        r"(\.//)?(((child::)?((\i\c*:)?(\i\c*|\*)))|\.)(/(((child::)?"
        r"((\i\c*:)?(\i\c*|\*)))|\.))*(\|(\.//)?(((child::)?((\i\c*:)?"
        r"(\i\c*|\*)))|\.)(/(((child::)?((\i\c*:)?(\i\c*|\*)))|\.))*)*",
        back_references=False,
        lazy_quantifiers=False,
        anchors=False
    )
    token = None
    parser = None

    def __init__(self, elem, schema, parent):
        super(XsdSelector, self).__init__(elem, schema, parent)

    def _parse(self):
        super(XsdSelector, self)._parse()
        try:
            self.path = self.elem.attrib['xpath']
        except KeyError:
            self.parse_error("'xpath' attribute required:", self.elem)
            self.path = '*'
        else:
            try:
                if not self.pattern.match(self.path.replace(' ', '')):
                    self.parse_error("invalid XPath expression for an {}".format(type(self)))
            except AttributeError:
                # Compile regex pattern
                self.__class__.pattern = re.compile(self.pattern)
                if not self.pattern.match(self.path.replace(' ', '')):
                    self.parse_error("invalid XPath expression for an {}".format(type(self)))

        # XSD 1.1 xpathDefaultNamespace attribute
        if self.schema.XSD_VERSION > '1.0':
            if 'xpathDefaultNamespace' in self.elem.attrib:
                self.xpath_default_namespace = self._parse_xpath_default_namespace(self.elem)
            else:
                self.xpath_default_namespace = self.schema.xpath_default_namespace

        self.parser = IdentityXPathParser(
            namespaces=self.namespaces,
            strict=False,
            compatibility_mode=True,
            default_namespace=self.xpath_default_namespace,
        )

        try:
            self.token = self.parser.parse(self.path)
        except ElementPathError as err:
            self.parse_error(err)
            self.token = self.parser.parse('*')

    def __repr__(self):
        return '%s(path=%r)' % (self.__class__.__name__, self.path)

    @property
    def built(self):
        return self.token is not None

    @property
    def target_namespace(self):
        if ':' in self.path:
            match = QNAME_PATTERN.findall(self.path)
            if match is not None:
                prefix = match[0][0]
                if prefix:
                    return self.namespaces[prefix]
                elif self.xpath_default_namespace:
                    return self.xpath_default_namespace

        return self.schema.target_namespace