Exemple #1
0
    def parse(cls, definitions, xmlelement):
        """
            <wsdl:binding name="nmtoken" type="qname"> *
                <-- extensibility element (1) --> *
                <wsdl:operation name="nmtoken"> *
                   <-- extensibility element (2) --> *
                   <wsdl:input name="nmtoken"? > ?
                       <-- extensibility element (3) -->
                   </wsdl:input>
                   <wsdl:output name="nmtoken"? > ?
                       <-- extensibility element (4) --> *
                   </wsdl:output>
                   <wsdl:fault name="nmtoken"> *
                       <-- extensibility element (5) --> *
                   </wsdl:fault>
                </wsdl:operation>
            </wsdl:binding>
        """
        name = qname_attr(xmlelement, 'name', definitions.target_namespace)
        port_name = qname_attr(xmlelement, 'type', definitions.target_namespace)

        # The soap:binding element contains the transport method and
        # default style attribute for the operations.
        soap_node = _soap_element(xmlelement, 'binding')
        transport = soap_node.get('transport')
        if transport != 'http://schemas.xmlsoap.org/soap/http':
            raise NotImplementedError("Only soap/http is supported for now")
        default_style = soap_node.get('style', 'document')

        obj = cls(definitions.wsdl, name, port_name, transport, default_style)
        for node in xmlelement.findall('wsdl:operation', namespaces=cls.nsmap):
            operation = SoapOperation.parse(definitions, node, obj, nsmap=cls.nsmap)
            obj._operation_add(operation)
        return obj
Exemple #2
0
    def parse(cls, definitions, xmlelement):
        """
            <wsdl:binding name="nmtoken" type="qname"> *
                <-- extensibility element (1) --> *
                <wsdl:operation name="nmtoken"> *
                   <-- extensibility element (2) --> *
                   <wsdl:input name="nmtoken"? > ?
                       <-- extensibility element (3) -->
                   </wsdl:input>
                   <wsdl:output name="nmtoken"? > ?
                       <-- extensibility element (4) --> *
                   </wsdl:output>
                   <wsdl:fault name="nmtoken"> *
                       <-- extensibility element (5) --> *
                   </wsdl:fault>
                </wsdl:operation>
            </wsdl:binding>
        """
        name = qname_attr(xmlelement, 'name', definitions.target_namespace)
        port_name = qname_attr(xmlelement, 'type', definitions.target_namespace)

        # The soap:binding element contains the transport method and
        # default style attribute for the operations.
        soap_node = xmlelement.find('soap:binding', namespaces=cls.nsmap)
        transport = soap_node.get('transport')
        if transport != 'http://schemas.xmlsoap.org/soap/http':
            raise NotImplementedError("Only soap/http is supported for now")
        default_style = soap_node.get('style', 'document')

        obj = cls(definitions.wsdl, name, port_name, transport, default_style)
        for node in xmlelement.findall('wsdl:operation', namespaces=cls.nsmap):
            operation = SoapOperation.parse(definitions, node, obj, nsmap=cls.nsmap)
            obj._operation_add(operation)
        return obj
Exemple #3
0
def parse_abstract_message(wsdl, xmlelement):
    """Create an AbstractMessage object from a xml element.

        <definitions .... >
            <message name="nmtoken"> *
                <part name="nmtoken" element="qname"? type="qname"?/> *
            </message>
        </definitions>
    """
    tns = wsdl.target_namespace
    parts = []

    for part in xmlelement.findall('wsdl:part', namespaces=NSMAP):
        part_name = part.get('name')
        part_element = qname_attr(part, 'element', tns)
        part_type = qname_attr(part, 'type', tns)

        if part_element is not None:
            part_element = wsdl.types.get_element(part_element)
        if part_type is not None:
            part_type = wsdl.types.get_type(part_type)

        part = definitions.MessagePart(part_element, part_type)
        parts.append((part_name, part))

    # Create the object, add the parts and return it
    message_name = qname_attr(xmlelement, 'name', tns)
    msg = definitions.AbstractMessage(message_name)
    for part_name, part in parts:
        msg.add_part(part_name, part)
    return msg
    def parse(cls, definitions, xmlelement):
        """
            <definitions .... >
                <message name="nmtoken"> *
                    <part name="nmtoken" element="qname"? type="qname"?/> *
                </message>
            </definitions>
        """
        msg = cls(
            name=qname_attr(xmlelement, 'name', definitions.target_namespace))

        for part in xmlelement.findall('wsdl:part', namespaces=NSMAP):
            part_name = part.get('name')

            part_element = qname_attr(part, 'element',
                                      definitions.target_namespace)
            part_type = qname_attr(part, 'type', definitions.target_namespace)

            if part_element is not None:
                part_element = definitions.schema.get_element(part_element)

            if part_type is not None:
                part_type = definitions.schema.get_type(part_type)

            msg.add_part(part_name, MessagePart(part_element, part_type))
        return msg
Exemple #5
0
    def visit_attribute(self, node, parent):
        """Declares an attribute.

            <attribute
              default = string
              fixed = string
              form = (qualified | unqualified)
              id = ID
              name = NCName
              ref = QName
              type = QName
              use = (optional | prohibited | required): optional
              {any attributes with non-schema Namespace...}>
            Content: (annotation?, (simpleType?))
            </attribute>
        """
        is_global = parent.tag == tags.schema

        # If the elment has a ref attribute then all other attributes cannot
        # be present. Short circuit that here.
        # Ref is prohibited on global elements (parent = schema)
        if not is_global:
            result = self.process_ref_attribute(node)
            if result:
                return result

        attribute_form = node.get('form', self.schema._attribute_form)
        qname = qname_attr(node, 'name', self.schema._target_namespace)
        if attribute_form == 'qualified':
            name = qname
        else:
            name = etree.QName(node.get('name'))

        xsd_type = None
        for child in node.iterchildren():
            if child.tag == tags.annotation:
                continue

            elif child.tag == tags.simpleType:
                assert xsd_type is None
                xsd_type = self.visit_simple_type(child, node)

        if xsd_type is None:
            node_type = qname_attr(node, 'type')
            xsd_type = self._get_type(node_type)

        # TODO: We ignore 'prohobited' for now
        required = node.get('use') == 'required'
        default = node.get('default')

        attr = xsd_elements.Attribute(
            name, type_=xsd_type, default=default, required=required)
        self.schema._elm_instances.append(attr)

        # Only register global elements
        if is_global:
            self.schema.register_attribute(qname, attr)
        return attr
Exemple #6
0
    def visit_attribute(self, node, parent):
        """Declares an attribute.

            <attribute
              default = string
              fixed = string
              form = (qualified | unqualified)
              id = ID
              name = NCName
              ref = QName
              type = QName
              use = (optional | prohibited | required): optional
              {any attributes with non-schema Namespace...}>
            Content: (annotation?, (simpleType?))
            </attribute>
        """
        is_global = parent.tag == tags.schema

        # If the elment has a ref attribute then all other attributes cannot
        # be present. Short circuit that here.
        # Ref is prohibited on global elements (parent = schema)
        if not is_global:
            result = self.process_ref_attribute(node)
            if result:
                return result

        attribute_form = node.get('form', self.schema._attribute_form)
        qname = qname_attr(node, 'name', self.schema._target_namespace)
        if attribute_form == 'qualified' or is_global:
            name = qname
        else:
            name = etree.QName(node.get('name'))

        annotation, items = self._pop_annotation(node.getchildren())
        if items:
            xsd_type = self.visit_simple_type(items[0], node)
        else:
            node_type = qname_attr(node, 'type')
            if node_type:
                xsd_type = self._get_type(node_type)
            else:
                xsd_type = xsd_builtins.AnyType()

        # TODO: We ignore 'prohobited' for now
        required = node.get('use') == 'required'
        default = node.get('default')

        attr = xsd_elements.Attribute(name,
                                      type_=xsd_type,
                                      default=default,
                                      required=required)
        self.schema._elm_instances.append(attr)

        # Only register global elements
        if is_global:
            self.schema.register_attribute(qname, attr)
        return attr
Exemple #7
0
    def parse(cls, definitions, xmlelement):
        name = qname_attr(xmlelement, 'name', definitions.target_namespace)
        port_name = qname_attr(xmlelement, 'type', definitions.target_namespace)

        obj = cls(definitions.wsdl, name, port_name)
        for node in xmlelement.findall('wsdl:operation', namespaces=NSMAP):
            operation = HttpOperation.parse(definitions, node, obj)
            obj._operation_add(operation)
        return obj
Exemple #8
0
    def parse(cls, definitions, xmlelement):
        name = qname_attr(xmlelement, 'name', definitions.target_namespace)
        port_name = qname_attr(xmlelement, 'type', definitions.target_namespace)

        obj = cls(definitions.wsdl, name, port_name)
        for node in xmlelement.findall('wsdl:operation', namespaces=NSMAP):
            operation = HttpOperation.parse(definitions, node, obj)
            obj._operation_add(operation)
        return obj
Exemple #9
0
    def parse(cls, wsdl, xmlelement):
        """
            <wsdl:port name="nmtoken" binding="qname"> *
               <wsdl:documentation .... /> ?
               <-- extensibility element -->
            </wsdl:port>

        """
        name = qname_attr(xmlelement, 'name', wsdl.target_namespace)
        binding_name = qname_attr(xmlelement, 'binding', wsdl.target_namespace)
        return cls(name.text, binding_name=binding_name, xmlelement=xmlelement)
Exemple #10
0
    def parse(cls, definitions, xmlelement, name, tag_name, operation, nsmap):
        """
        Example::

              <output>
                <soap:body use="literal"/>
              </output>

        """
        obj = cls(definitions.wsdl, name, operation, nsmap=nsmap)

        tns = definitions.target_namespace
        body = _soap_element(xmlelement, 'body')
        header = _soap_element(xmlelement, 'header')
        headerfault = _soap_element(xmlelement, 'headerfault')

        obj._info = {
            'body': {}, 'header': {}, 'headerfault': {}
        }

        if body is not None:
            obj._info['body'] = {
                'part': body.get('part'),
                'use': body.get('use', 'literal'),
                'encodingStyle': body.get('encodingStyle'),
                'namespace': body.get('namespace'),
            }

        if header is not None:
            obj._info['header'] = {
                'message': qname_attr(header, 'message', tns),
                'part': header.get('part'),
                'use': header.get('use', 'literal'),
                'encodingStyle': header.get('encodingStyle'),
                'namespace': header.get('namespace'),
            }

        if headerfault is not None:
            obj._info['headerfault'] = {
                'message': qname_attr(headerfault, 'message', tns),
                'part': headerfault.get('part'),
                'use': headerfault.get('use', 'literal'),
                'encodingStyle': headerfault.get('encodingStyle'),
                'namespace': headerfault.get('namespace'),
            }

        obj.namespace = {
            'body': obj._info['body'].get('namespace'),
            'header': obj._info['header'].get('namespace'),
            'headerfault': obj._info['headerfault'].get('namespace'),
        }
        return obj
Exemple #11
0
def parse_abstract_message(
        wsdl, xmlelement: etree._Element) -> definitions.AbstractMessage:
    """Create an AbstractMessage object from a xml element.

    Definition::

        <definitions .... >
            <message name="nmtoken"> *
                <part name="nmtoken" element="qname"? type="qname"?/> *
            </message>
        </definitions>

    :param wsdl: The parent definition instance
    :type wsdl: zeep.wsdl.wsdl.Definition
    :param xmlelement: The XML node
    :type xmlelement: lxml.etree._Element
    :rtype: zeep.wsdl.definitions.AbstractMessage

    """
    tns = wsdl.target_namespace
    message_name = qname_attr(xmlelement, "name", tns)
    if not message_name:
        raise IncompleteMessage(
            "Message element is missing required name attribute")

    parts = []

    for part in xmlelement.findall("wsdl:part", namespaces=NSMAP):
        part_name = part.get("name")
        part_element = qname_attr(part, "element")
        part_type = qname_attr(part, "type")

        try:
            if part_element is not None:
                part_element = wsdl.types.get_element(part_element)
            if part_type is not None:
                part_type = wsdl.types.get_type(part_type)

        except (NamespaceError, LookupError):
            raise IncompleteMessage(
                ("The wsdl:message for %r contains an invalid part (%r): "
                 "invalid xsd type or elements") %
                (message_name.text, part_name))

        part = definitions.MessagePart(part_element, part_type)
        parts.append((part_name, part))

    # Create the object, add the parts and return it
    msg = definitions.AbstractMessage(message_name)
    for part_name, part in parts:
        msg.add_part(part_name, part)
    return msg
    def parse(cls, wsdl, xmlelement):
        name = qname_attr(xmlelement, 'name', wsdl.target_namespace)
        port_name = qname_attr(xmlelement, 'type', wsdl.target_namespace)
        port_type = wsdl.ports[port_name.text]

        obj = cls(name, port_type)

        for node in xmlelement.findall('wsdl:operation', namespaces=NSMAP):
            operation = HttpOperation.parse(wsdl, node, obj)

            # XXX: operation name is not unique
            obj.operations[operation.name.text] = operation
        return obj
Exemple #13
0
    def parse(cls, definitions, xmlelement, operation, nsmap):
        """
        Example::

              <output>
                <soap:body use="literal"/>
              </output>

        """
        name = xmlelement.get('name')
        obj = cls(definitions.wsdl, name, operation, nsmap=nsmap)

        tns = definitions.target_namespace

        info = {
            'body': {},
            'header': {},
            'headerfault': {}
        }

        body = _soap_element(xmlelement, 'body')
        if body is not None:
            info['body'] = {
                'part': body.get('part'),
                'use': body.get('use', 'literal'),
                'encodingStyle': body.get('encodingStyle'),
                'namespace': body.get('namespace'),
            }

        header = _soap_element(xmlelement, 'header')
        if header is not None:
            info['header'] = {
                'message': qname_attr(header, 'message', tns),
                'part': header.get('part'),
                'use': header.get('use', 'literal'),
                'encodingStyle': header.get('encodingStyle'),
                'namespace': header.get('namespace'),
            }

        headerfault = _soap_element(xmlelement, 'headerfault')
        if headerfault is not None:
            info['headerfault'] = {
                'message': qname_attr(headerfault, 'message', tns),
                'part': headerfault.get('part'),
                'use': headerfault.get('use', 'literal'),
                'encodingStyle': headerfault.get('encodingStyle'),
                'namespace': headerfault.get('namespace'),
            }

        obj._info = info
        return obj
Exemple #14
0
    def parse(cls, definitions, xmlelement):
        """

        Definition::

            <wsdl:binding name="nmtoken" type="qname"> *
                <-- extensibility element (1) --> *
                <wsdl:operation name="nmtoken"> *
                   <-- extensibility element (2) --> *
                   <wsdl:input name="nmtoken"? > ?
                       <-- extensibility element (3) -->
                   </wsdl:input>
                   <wsdl:output name="nmtoken"? > ?
                       <-- extensibility element (4) --> *
                   </wsdl:output>
                   <wsdl:fault name="nmtoken"> *
                       <-- extensibility element (5) --> *
                   </wsdl:fault>
                </wsdl:operation>
            </wsdl:binding>
        """
        name = qname_attr(xmlelement, "name", definitions.target_namespace)
        port_name = qname_attr(xmlelement, "type",
                               definitions.target_namespace)

        # The soap:binding element contains the transport method and
        # default style attribute for the operations.
        soap_node = xmlelement.find("soap:binding", namespaces=cls.nsmap)
        transport = soap_node.get("transport")

        supported_transports = [
            "http://schemas.xmlsoap.org/soap/http",
            "http://www.w3.org/2003/05/soap/bindings/HTTP/",
        ]

        if transport not in supported_transports:
            raise NotImplementedError(
                "The binding transport %s is not supported (only soap/http)" %
                (transport))
        default_style = soap_node.get("style", "document")

        obj = cls(definitions.wsdl, name, port_name, transport, default_style)
        for node in xmlelement.findall("wsdl:operation", namespaces=cls.nsmap):
            operation = SoapOperation.parse(definitions,
                                            node,
                                            obj,
                                            nsmap=cls.nsmap)
            operation.name = unique_op_name(operation.name, obj._operations)
            obj._operation_add(operation)
        return obj
Exemple #15
0
def parse_abstract_operation(wsdl, xmlelement):
    """Create an AbstractOperation object from a xml element.

    This is called from the parse_port_type function since the abstract
    operations are part of the port type element.

    Definition::

        <wsdl:operation name="nmtoken">*
           <wsdl:documentation .... /> ?
           <wsdl:input name="nmtoken"? message="qname">?
               <wsdl:documentation .... /> ?
           </wsdl:input>
           <wsdl:output name="nmtoken"? message="qname">?
               <wsdl:documentation .... /> ?
           </wsdl:output>
           <wsdl:fault name="nmtoken" message="qname"> *
               <wsdl:documentation .... /> ?
           </wsdl:fault>
        </wsdl:operation>

    :param wsdl: The parent definition instance
    :type wsdl: zeep.wsdl.wsdl.Definition
    :param xmlelement: The XML node
    :type xmlelement: lxml.etree._Element
    :rtype: zeep.wsdl.definitions.AbstractOperation

    """
    name = xmlelement.get('name')
    kwargs = {
        'fault_messages': {}
    }

    for msg_node in xmlelement.getchildren():
        tag_name = etree.QName(msg_node.tag).localname
        if tag_name not in ('input', 'output', 'fault'):
            continue

        param_msg = qname_attr(
            msg_node, 'message', wsdl.target_namespace)
        param_name = msg_node.get('name')

        try:
            param_value = wsdl.get('messages', param_msg.text)
        except IndexError:
            return

        if tag_name == 'input':
            kwargs['input_message'] = param_value
        elif tag_name == 'output':
            kwargs['output_message'] = param_value
        else:
            kwargs['fault_messages'][param_name] = param_value

        wsa_action = msg_node.get(etree.QName(NSMAP['wsaw'], 'Action'))
        param_value.wsa_action = wsa_action

    kwargs['name'] = name
    kwargs['parameter_order'] = xmlelement.get('parameterOrder')
    return definitions.AbstractOperation(**kwargs)
Exemple #16
0
    def visit_restriction_simple_content(self, node, parent):
        """
        Definition::

            <restriction
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?,
                (simpleType?, (
                    minExclusive | minInclusive | maxExclusive | maxInclusive |
                    totalDigits |fractionDigits | length | minLength |
                    maxLength | enumeration | whiteSpace | pattern)*
                )?, ((attribute | attributeGroup)*, anyAttribute?))
            </restriction>

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element

        """
        base_name = qname_attr(node, 'base')
        base_type = self._get_type(base_name)
        return base_type, []
Exemple #17
0
    def visit_restriction_simple_type(self, node, parent):
        """
        Definition::

            <restriction
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?,
                (simpleType?, (
                    minExclusive | minInclusive | maxExclusive | maxInclusive |
                    totalDigits |fractionDigits | length | minLength |
                    maxLength | enumeration | whiteSpace | pattern)*))
            </restriction>

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element

        """
        base_name = qname_attr(node, 'base')
        if base_name:
            return self._get_type(base_name)

        annotation, children = self._pop_annotation(node.getchildren())
        if children[0].tag == tags.simpleType:
            return self.visit_simple_type(children[0], node)
Exemple #18
0
    def parse(self, xmlelement, schema, allow_none=False, context=None):
        """Process the given xmlelement. If it has an xsi:type attribute then
        use that for further processing. This should only be done for subtypes
        of the defined type but for now we just accept everything.

        This is the entrypoint for parsing an xml document.

        :param xmlelement: The XML element to parse
        :type xmlelements: lxml.etree._Element
        :param schema: The parent XML schema
        :type schema: zeep.xsd.Schema
        :param allow_none: Allow none
        :type allow_none: bool
        :param context: Optional parsing context (for inline schemas)
        :type context: zeep.xsd.context.XmlParserContext
        :return: dict or None

        """
        context = context or XmlParserContext()
        instance_type = qname_attr(xmlelement, xsi_ns('type'))
        xsd_type = None
        if instance_type:
            xsd_type = schema.get_type(instance_type, fail_silently=True)
        xsd_type = xsd_type or self.type
        return xsd_type.parse_xmlelement(
            xmlelement, schema, allow_none=allow_none, context=context,
            schema_type=self.type)
Exemple #19
0
    def visit_restriction_complex_content(self, node, parent):
        """

        Definition::

            <restriction
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (group | all | choice | sequence)?,
                    ((attribute | attributeGroup)*, anyAttribute?))
            </restriction>

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element

        """
        base_name = qname_attr(node, 'base')
        base_type = self._get_type(base_name)
        annotation, children = self._pop_annotation(node.getchildren())

        element = None
        attributes = []

        if children:
            child = children[0]
            if child.tag in (tags.group, tags.all, tags.choice, tags.sequence):
                children.pop(0)
                element = self.process(child, node)
            attributes = self._process_attributes(node, children)
        return base_type, element, attributes
Exemple #20
0
    def parse(self, xmlelement, schema, context=None):
        if self.process_contents == "skip":
            return xmlelement

        # If a schema was passed inline then check for a matching one
        qname = etree.QName(xmlelement.tag)
        if context and context.schemas:
            for context_schema in context.schemas:
                if context_schema.documents.has_schema_document_for_ns(qname.namespace):
                    schema = context_schema
                    break
            else:
                # Try to parse the any result by iterating all the schemas
                for context_schema in context.schemas:
                    try:
                        data = context_schema.deserialize(list(xmlelement)[0])
                        return data
                    except LookupError:
                        continue

        # Lookup type via xsi:type attribute
        xsd_type = qname_attr(xmlelement, xsi_ns("type"))
        if xsd_type is not None:
            xsd_type = schema.get_type(xsd_type)
            return xsd_type.parse_xmlelement(xmlelement, schema, context=context)

        # Check if a restrict is used
        if self.restrict:
            return self.restrict.parse_xmlelement(xmlelement, schema, context=context)

        try:
            element = schema.get_element(xmlelement.tag)
            return element.parse(xmlelement, schema, context=context)
        except (exceptions.NamespaceError, exceptions.LookupError):
            return xmlelement
Exemple #21
0
    def visit_list(self, node, parent):
        """
        Definition::

            <list
              id = ID
              itemType = QName
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (simpleType?))
            </list>

        The use of the simpleType element child and the itemType attribute is
        mutually exclusive.

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element


        """
        item_type = qname_attr(node, 'itemType')
        if item_type:
            sub_type = self._get_type(item_type.text)
        else:
            subnodes = node.getchildren()
            child = subnodes[-1]  # skip annotation
            sub_type = self.visit_simple_type(child, node)
        return xsd_types.ListType(sub_type)
Exemple #22
0
    def visit_extension_complex_content(self, node, parent):
        """
            <extension
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (
                        (group | all | choice | sequence)?,
                        ((attribute | attributeGroup)*, anyAttribute?)))
            </extension>
        """
        base_name = qname_attr(node, 'base')
        try:
            base = self.schema.get_type(base_name)
            children = base._children
        except KeyError:
            children = [xsd_types.UnresolvedType(base_name)]

        for child in node.iterchildren():
            if child.tag == tags.annotation:
                continue

            item = self.process(child, node)

            if child.tag == tags.group:
                children.extend(item)

            elif child.tag in (tags.choice, tags.sequence, tags.all):
                children.extend(item)

            elif child.tag in (tags.attribute, ):
                children.append(item)

        return children
Exemple #23
0
    def visit_group(self, node, parent):
        """
            <group
              name= NCName
              id = ID
              maxOccurs = (nonNegativeInteger | unbounded) : 1
              minOccurs = nonNegativeInteger : 1
              name = NCName
              ref = QName
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (all | choice | sequence))
            </group>
        """

        result = self.process_ref_attribute(node)
        if result:
            return result

        qname = qname_attr(node, 'name', self.schema._target_namespace)

        # There should be only max nodes, first node (annotation) is irrelevant
        subnodes = node.getchildren()
        child = subnodes[-1]
        children = self.process(child, parent)

        elm = xsd_elements.GroupElement(name=qname, children=children)

        if parent.tag == tags.schema:
            self.schema.register_element(qname, elm)
        return elm
Exemple #24
0
    def visit_attribute_group(self, node, parent):
        """
        Definition::

            <attributeGroup
              id = ID
              name = NCName
              ref = QName
              {any attributes with non-schema Namespace...}>
            Content: (annotation?),
                     ((attribute | attributeGroup)*, anyAttribute?))
            </attributeGroup>

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element

        """
        ref = self.process_reference(node)
        if ref:
            return ref

        qname = qname_attr(node, 'name', self.document._target_namespace)
        annotation, children = self._pop_annotation(node.getchildren())

        attributes = self._process_attributes(node, children)
        attribute_group = xsd_elements.AttributeGroup(qname, attributes)
        self.register_attribute_group(qname, attribute_group)
Exemple #25
0
def parse_abstract_operation(wsdl, xmlelement):
    """Create an AbstractOperation object from a xml element.

    This is called from the parse_port_type function since the abstract
    operations are part of the port type element.

    Definition::

        <wsdl:operation name="nmtoken">*
           <wsdl:documentation .... /> ?
           <wsdl:input name="nmtoken"? message="qname">?
               <wsdl:documentation .... /> ?
           </wsdl:input>
           <wsdl:output name="nmtoken"? message="qname">?
               <wsdl:documentation .... /> ?
           </wsdl:output>
           <wsdl:fault name="nmtoken" message="qname"> *
               <wsdl:documentation .... /> ?
           </wsdl:fault>
        </wsdl:operation>

    :param wsdl: The parent definition instance
    :type wsdl: zeep.wsdl.wsdl.Definition
    :param xmlelement: The XML node
    :type xmlelement: lxml.etree._Element
    :rtype: zeep.wsdl.definitions.AbstractOperation

    """
    name = xmlelement.get('name')
    kwargs = {
        'fault_messages': {}
    }

    for msg_node in xmlelement:
        tag_name = etree.QName(msg_node.tag).localname
        if tag_name not in ('input', 'output', 'fault'):
            continue

        param_msg = qname_attr(
            msg_node, 'message', wsdl.target_namespace)
        param_name = msg_node.get('name')

        try:
            param_value = wsdl.get('messages', param_msg.text)
        except IndexError:
            return

        if tag_name == 'input':
            kwargs['input_message'] = param_value
        elif tag_name == 'output':
            kwargs['output_message'] = param_value
        else:
            kwargs['fault_messages'][param_name] = param_value

        wsa_action = msg_node.get(etree.QName(NSMAP['wsaw'], 'Action'))
        param_value.wsa_action = wsa_action

    kwargs['name'] = name
    kwargs['parameter_order'] = xmlelement.get('parameterOrder')
    return definitions.AbstractOperation(**kwargs)
Exemple #26
0
def parse_port(wsdl, xmlelement):
    """Create a Port object from a xml element.

    This is called via the parse_service function since ports are part of the
    service xml elements.

    Definition::

        <wsdl:port name="nmtoken" binding="qname"> *
           <wsdl:documentation .... /> ?
           <-- extensibility element -->
        </wsdl:port>

    :param wsdl: The parent definition instance
    :type wsdl: zeep.wsdl.wsdl.Definition
    :param xmlelement: The XML node
    :type xmlelement: lxml.etree._Element
    :rtype: zeep.wsdl.definitions.Port

    """
    name = xmlelement.get('name')
    binding_name = qname_attr(xmlelement, 'binding', wsdl.target_namespace)
    return definitions.Port(name,
                            binding_name=binding_name,
                            xmlelement=xmlelement)
Exemple #27
0
    def parse(cls, definitions, xmlelement):
        """

        Syntax::

            <wsdl:service name="nmtoken"> *
                <wsdl:documentation .... />?
                <wsdl:port name="nmtoken" binding="qname"> *
                   <wsdl:documentation .... /> ?
                   <-- extensibility element -->
                </wsdl:port>
                <-- extensibility element -->
            </wsdl:service>

        Example::

              <service name="StockQuoteService">
                <documentation>My first service</documentation>
                <port name="StockQuotePort" binding="tns:StockQuoteBinding">
                  <soap:address location="http://example.com/stockquote"/>
                </port>
              </service>

        """
        name = qname_attr(xmlelement, 'name', definitions.target_namespace)
        obj = cls(name)
        for port_node in xmlelement.findall('wsdl:port', namespaces=NSMAP):
            port = Port.parse(definitions, port_node)
            if port:
                obj.add_port(port)

        return obj
Exemple #28
0
    def parse(self, xmlelement, schema, allow_none=False, context=None):
        """Process the given xmlelement. If it has an xsi:type attribute then
        use that for further processing. This should only be done for subtypes
        of the defined type but for now we just accept everything.

        This is the entrypoint for parsing an xml document.

        :param xmlelement: The XML element to parse
        :type xmlelements: lxml.etree._Element
        :param schema: The parent XML schema
        :type schema: zeep.xsd.Schema
        :param allow_none: Allow none
        :type allow_none: bool
        :param context: Optional parsing context (for inline schemas)
        :type context: zeep.xsd.context.XmlParserContext
        :return: dict or None

        """
        context = context or XmlParserContext()
        instance_type = qname_attr(xmlelement, xsi_ns('type'))
        xsd_type = None
        if instance_type:
            xsd_type = schema.get_type(instance_type, fail_silently=True)
        xsd_type = xsd_type or self.type
        return xsd_type.parse_xmlelement(
            xmlelement, schema, allow_none=allow_none, context=context,
            schema_type=self.type)
Exemple #29
0
    def parse(cls, definitions, xmlelement):
        """
            <wsdl:operation name="nmtoken">*
               <wsdl:documentation .... /> ?
               <wsdl:input name="nmtoken"? message="qname">?
                   <wsdl:documentation .... /> ?
               </wsdl:input>
               <wsdl:output name="nmtoken"? message="qname">?
                   <wsdl:documentation .... /> ?
               </wsdl:output>
               <wsdl:fault name="nmtoken" message="qname"> *
                   <wsdl:documentation .... /> ?
               </wsdl:fault>
            </wsdl:operation>
        """
        name = xmlelement.get('name')
        kwargs = {
            'faults': {}
        }

        for msg_node in xmlelement.getchildren():
            tag_name = etree.QName(msg_node.tag).localname
            if tag_name not in ('input', 'output', 'fault'):
                continue

            param_msg = qname_attr(msg_node, 'message', definitions.target_namespace)
            param_name = msg_node.get('name')
            if tag_name in ('input', 'output'):
                kwargs[tag_name] = definitions.messages[param_msg.text]
            else:
                kwargs['faults'][param_name] = definitions.messages[param_msg.text]

        kwargs['name'] = name
        kwargs['parameter_order'] = xmlelement.get('parameterOrder')
        return cls(**kwargs)
Exemple #30
0
def parse_port_type(wsdl, xmlelement):
    """Create a PortType object from a xml element.

    Definition::

        <wsdl:definitions .... >
            <wsdl:portType name="nmtoken">
                <wsdl:operation name="nmtoken" .... /> *
            </wsdl:portType>
        </wsdl:definitions>

    :param wsdl: The parent definition instance
    :type wsdl: zeep.wsdl.wsdl.Definition
    :param xmlelement: The XML node
    :type xmlelement: lxml.etree._Element
    :rtype: zeep.wsdl.definitions.PortType

    """
    name = qname_attr(xmlelement, 'name', wsdl.target_namespace)
    operations = {}
    for elm in xmlelement.findall('wsdl:operation', namespaces=NSMAP):
        operation = parse_abstract_operation(wsdl, elm)
        if operation:
            operations[operation.name] = operation
    return definitions.PortType(name, operations)
Exemple #31
0
    def parse(cls, definitions, xmlelement):
        """
            <wsdl:operation name="nmtoken">*
               <wsdl:documentation .... /> ?
               <wsdl:input name="nmtoken"? message="qname">?
                   <wsdl:documentation .... /> ?
               </wsdl:input>
               <wsdl:output name="nmtoken"? message="qname">?
                   <wsdl:documentation .... /> ?
               </wsdl:output>
               <wsdl:fault name="nmtoken" message="qname"> *
                   <wsdl:documentation .... /> ?
               </wsdl:fault>
            </wsdl:operation>
        """
        name = xmlelement.get('name')
        kwargs = {'faults': {}}

        for msg_node in xmlelement.getchildren():
            tag_name = etree.QName(msg_node.tag).localname
            if tag_name not in ('input', 'output', 'fault'):
                continue

            param_msg = qname_attr(msg_node, 'message',
                                   definitions.target_namespace)
            param_name = msg_node.get('name')
            param_value = definitions.get('messages', param_msg.text)
            if tag_name in ('input', 'output'):
                kwargs[tag_name] = param_value
            else:
                kwargs['faults'][param_name] = param_value

        kwargs['name'] = name
        kwargs['parameter_order'] = xmlelement.get('parameterOrder')
        return cls(**kwargs)
Exemple #32
0
def parse_port_type(
    wsdl: "Definition", xmlelement: etree._Element
) -> definitions.PortType:
    """Create a PortType object from a xml element.

    Definition::

        <wsdl:definitions .... >
            <wsdl:portType name="nmtoken">
                <wsdl:operation name="nmtoken" .... /> *
            </wsdl:portType>
        </wsdl:definitions>

    :param wsdl: The parent definition instance
    :param xmlelement: The XML node

    """
    name = qname_attr(xmlelement, "name", wsdl.target_namespace)
    assert name is not None
    operations = {}  # type: typing.Dict[str, definitions.AbstractOperation]
    for elm in xmlelement.findall("wsdl:operation", namespaces=NSMAP):
        operation = parse_abstract_operation(wsdl, elm)
        if operation:
            operations[operation.name] = operation

    return definitions.PortType(name, operations)
Exemple #33
0
def parse_port_type(wsdl, xmlelement):
    """Create a PortType object from a xml element.

    Definition::

        <wsdl:definitions .... >
            <wsdl:portType name="nmtoken">
                <wsdl:operation name="nmtoken" .... /> *
            </wsdl:portType>
        </wsdl:definitions>

    :param wsdl: The parent definition instance
    :type wsdl: zeep.wsdl.wsdl.Definition
    :param xmlelement: The XML node
    :type xmlelement: lxml.etree._Element
    :rtype: zeep.wsdl.definitions.PortType

    """
    name = qname_attr(xmlelement, 'name', wsdl.target_namespace)
    operations = {}
    for elm in xmlelement.findall('wsdl:operation', namespaces=NSMAP):
        operation = parse_abstract_operation(wsdl, elm)
        if operation:
            operations[operation.name] = operation
    return definitions.PortType(name, operations)
Exemple #34
0
    def parse_xmlelement(self,
                         xmlelement,
                         schema=None,
                         allow_none=True,
                         context=None):
        xsi_type = qname_attr(xmlelement, xsi_ns('type'))
        xsi_nil = xmlelement.get(xsi_ns('nil'))

        # Handle xsi:nil attribute
        if xsi_nil == "true":
            return None

        if xsi_type and schema:
            xsd_type = schema.get_type(xsi_type, fail_silently=True)

            # If we were unable to resolve a type for the xsi:type (due to
            # buggy soap servers) then we just return the lxml element.
            if not xsd_type:
                return xmlelement.getchildren()

            # If the xsd_type is xsd:anyType then we will recurs so ignore
            # that.
            if isinstance(xsd_type, self.__class__):
                return xmlelement.text or None

            return xsd_type.parse_xmlelement(xmlelement,
                                             schema,
                                             context=context)

        if xmlelement.text is None:
            return

        return self.pythonvalue(xmlelement.text)
Exemple #35
0
    def parse_xmlelement(self,
                         xmlelement,
                         schema=None,
                         allow_none=True,
                         context=None):
        xsi_type = qname_attr(xmlelement, xsi_ns('type'))
        xsi_nil = xmlelement.get(xsi_ns('nil'))

        # Handle xsi:nil attribute
        if xsi_nil == "true":
            return None

        if xsi_type and schema:
            xsd_type = schema.get_type(xsi_type)

            # If the xsd_type is xsd:anyType then we will recurs so ignore
            # that.
            if isinstance(xsd_type, self.__class__):
                return xmlelement.text or None

            return xsd_type.parse_xmlelement(xmlelement,
                                             schema,
                                             context=context)

        if xmlelement.text is None:
            return

        return self.pythonvalue(xmlelement.text)
Exemple #36
0
    def parse_xmlelement(self, xmlelement, schema=None, allow_none=True,
                         context=None):
        xsi_type = qname_attr(xmlelement, xsi_ns('type'))
        xsi_nil = xmlelement.get(xsi_ns('nil'))

        # Handle xsi:nil attribute
        if xsi_nil == "true":
            return None

        if xsi_type and schema:
            xsd_type = schema.get_type(xsi_type, fail_silently=True)

            # If we were unable to resolve a type for the xsi:type (due to
            # buggy soap servers) then we just return the lxml element.
            if not xsd_type:
                return xmlelement.getchildren()

            # If the xsd_type is xsd:anyType then we will recurs so ignore
            # that.
            if isinstance(xsd_type, self.__class__):
                return xmlelement.text or None

            return xsd_type.parse_xmlelement(
                xmlelement, schema, context=context)

        if xmlelement.text is None:
            return

        return self.pythonvalue(xmlelement.text)
Exemple #37
0
    def parse(self, xmlelement, schema, context=None):
        if self.process_contents == 'skip':
            return xmlelement

        # If a schema was passed inline then check for a matching one
        qname = etree.QName(xmlelement.tag)
        if context and context.schemas:
            for context_schema in context.schemas:
                if context_schema.documents.has_schema_document_for_ns(qname.namespace):
                    schema = context_schema
                    break

        # Lookup type via xsi:type attribute
        xsd_type = qname_attr(xmlelement, xsi_ns('type'))
        if xsd_type is not None:
            xsd_type = schema.get_type(xsd_type)
            return xsd_type.parse_xmlelement(xmlelement, schema, context=context)

        # Check if a restrict is used
        if self.restrict:
            return self.restrict.parse_xmlelement(
                xmlelement, schema, context=context)

        try:
            element = schema.get_element(xmlelement.tag)
            return element.parse(xmlelement, schema, context=context)
        except (exceptions.NamespaceError, exceptions.LookupError):
            return xmlelement
Exemple #38
0
    def visit_extension_complex_content(self, node, parent):
        """
            <extension
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (
                        (group | all | choice | sequence)?,
                        ((attribute | attributeGroup)*, anyAttribute?)))
            </extension>
        """
        base_name = qname_attr(node, 'base')
        base_type = self._get_type(base_name)
        annotation, children = self._pop_annotation(node.getchildren())

        element = None
        attributes = []

        if children:
            child = children[0]
            if child.tag in (tags.group, tags.all, tags.choice, tags.sequence):
                children.pop(0)
                element = self.process(child, node)
            attributes = self._process_attributes(node, children)

        return base_type, element, attributes
Exemple #39
0
    def visit_extension_simple_content(self, node, parent):
        """
            <extension
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?))
            </extension>
        """
        base_name = qname_attr(node, 'base')
        try:
            base = self.schema.get_type(base_name)
            if isinstance(base, xsd_types.ComplexType):
                children = base._children
            else:
                children = [xsd_elements.Element(None, base)]
        except KeyError:
            children = [xsd_types.UnresolvedType(base_name)]

        for child in node.iterchildren():
            if child.tag == tags.annotation:
                continue

            item = self.process(child, node)
            if child.tag in (tags.attribute, ):
                children.append(item)

        return children
Exemple #40
0
    def visit_extension_simple_content(self, node, parent):
        """
            <extension
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?))
            </extension>
        """
        base_name = qname_attr(node, 'base')
        try:
            base = self.schema.get_type(base_name)
            if isinstance(base, xsd_types.ComplexType):
                children = base._children
            else:
                children = [xsd_elements.Element(None, base)]
        except KeyError:
            children = [xsd_types.UnresolvedType(base_name)]

        for child in node.iterchildren():
            if child.tag == tags.annotation:
                continue

            item = self.process(child, node)
            if child.tag in (tags.attribute,):
                children.append(item)

        return children
Exemple #41
0
    def parse(self, xmlelement, schema, context=None):
        if self.process_contents == 'skip':
            return xmlelement

        # If a schema was passed inline then check for a matching one
        qname = etree.QName(xmlelement.tag)
        if context and context.schemas:
            for context_schema in context.schemas:
                if context_schema.documents.has_schema_document_for_ns(
                        qname.namespace):
                    schema = context_schema
                    break

        # Lookup type via xsi:type attribute
        xsd_type = qname_attr(xmlelement, xsi_ns('type'))
        if xsd_type is not None:
            xsd_type = schema.get_type(xsd_type)
            return xsd_type.parse_xmlelement(xmlelement,
                                             schema,
                                             context=context)

        # Check if a restrict is used
        if self.restrict:
            return self.restrict.parse_xmlelement(xmlelement,
                                                  schema,
                                                  context=context)

        try:
            element = schema.get_element(xmlelement.tag)
            return element.parse(xmlelement, schema, context=context)
        except (exceptions.NamespaceError, exceptions.LookupError):
            return xmlelement
Exemple #42
0
    def visit_group(self, node, parent):
        """Groups a set of element declarations so that they can be
        incorporated as a group into complex type definitions.

            <group
              name= NCName
              id = ID
              maxOccurs = (nonNegativeInteger | unbounded) : 1
              minOccurs = nonNegativeInteger : 1
              name = NCName
              ref = QName
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (all | choice | sequence))
            </group>

        """

        result = self.process_reference(node)
        if result:
            return result

        qname = qname_attr(node, 'name', self.document._target_namespace)

        # There should be only max nodes, first node (annotation) is irrelevant
        annotation, children = self._pop_annotation(node.getchildren())
        child = children[0]

        item = self.process(child, parent)
        elm = xsd_elements.Group(name=qname, child=item)

        if parent.tag == tags.schema:
            self.document.register_group(qname, elm)
        return elm
Exemple #43
0
    def visit_group(self, node, parent):
        """
            <group
              name= NCName
              id = ID
              maxOccurs = (nonNegativeInteger | unbounded) : 1
              minOccurs = nonNegativeInteger : 1
              name = NCName
              ref = QName
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (all | choice | sequence))
            </group>
        """

        result = self.process_ref_attribute(node)
        if result:
            return result

        qname = qname_attr(node, 'name', self.schema._target_namespace)

        # There should be only max nodes, first node (annotation) is irrelevant
        subnodes = node.getchildren()
        child = subnodes[-1]
        children = self.process(child, parent)

        elm = xsd_elements.GroupElement(name=qname, children=children)

        if parent.tag == tags.schema:
            self.schema.register_element(qname, elm)
        return elm
Exemple #44
0
    def visit_restriction_simple_content(self, node, parent):
        """
        Definition::

            <restriction
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?,
                (simpleType?, (
                    minExclusive | minInclusive | maxExclusive | maxInclusive |
                    totalDigits |fractionDigits | length | minLength |
                    maxLength | enumeration | whiteSpace | pattern)*
                )?, ((attribute | attributeGroup)*, anyAttribute?))
            </restriction>

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element

        """
        base_name = qname_attr(node, "base")
        base_type = self._get_type(base_name)
        return base_type, []
Exemple #45
0
    def visit_restriction_simple_type(self, node, parent):
        """
        Definition::

            <restriction
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?,
                (simpleType?, (
                    minExclusive | minInclusive | maxExclusive | maxInclusive |
                    totalDigits |fractionDigits | length | minLength |
                    maxLength | enumeration | whiteSpace | pattern)*))
            </restriction>

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element

        """
        base_name = qname_attr(node, "base")
        if base_name:
            return self._get_type(base_name)

        annotation, children = self._pop_annotation(list(node))
        if children[0].tag == tags.simpleType:
            return self.visit_simple_type(children[0], node)
Exemple #46
0
    def visit_list(self, node, parent):
        """
        Definition::

            <list
              id = ID
              itemType = QName
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (simpleType?))
            </list>

        The use of the simpleType element child and the itemType attribute is
        mutually exclusive.

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element


        """
        item_type = qname_attr(node, "itemType")
        if item_type:
            sub_type = self._get_type(item_type.text)
        else:
            subnodes = list(node)
            child = subnodes[-1]  # skip annotation
            sub_type = self.visit_simple_type(child, node)
        return xsd_types.ListType(sub_type)
Exemple #47
0
    def visit_attribute_group(self, node, parent):
        """
        Definition::

            <attributeGroup
              id = ID
              name = NCName
              ref = QName
              {any attributes with non-schema Namespace...}>
            Content: (annotation?),
                     ((attribute | attributeGroup)*, anyAttribute?))
            </attributeGroup>

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element

        """
        ref = self.process_reference(node)
        if ref:
            return ref

        qname = qname_attr(node, "name", self.document._target_namespace)
        annotation, children = self._pop_annotation(list(node))

        attributes = self._process_attributes(node, children)
        attribute_group = xsd_elements.AttributeGroup(qname, attributes)
        self.register_attribute_group(qname, attribute_group)
Exemple #48
0
    def visit_extension_complex_content(self, node, parent):
        """
            <extension
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (
                        (group | all | choice | sequence)?,
                        ((attribute | attributeGroup)*, anyAttribute?)))
            </extension>
        """
        base_name = qname_attr(node, 'base')
        base_type = self._get_type(base_name)
        annotation, children = self._pop_annotation(node.getchildren())

        element = None
        attributes = []

        if children:
            child = children[0]
            if child.tag in (tags.group, tags.all, tags.choice, tags.sequence):
                children.pop(0)
                element = self.process(child, node)
            attributes = self._process_attributes(node, children)

        return base_type, element, attributes
Exemple #49
0
    def visit_group(self, node, parent):
        """Groups a set of element declarations so that they can be
        incorporated as a group into complex type definitions.

            <group
              name= NCName
              id = ID
              maxOccurs = (nonNegativeInteger | unbounded) : 1
              minOccurs = nonNegativeInteger : 1
              name = NCName
              ref = QName
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (all | choice | sequence))
            </group>

        """

        result = self.process_reference(node)
        if result:
            return result

        qname = qname_attr(node, 'name', self.document._target_namespace)

        # There should be only max nodes, first node (annotation) is irrelevant
        annotation, children = self._pop_annotation(node.getchildren())
        child = children[0]

        item = self.process(child, parent)
        elm = xsd_indicators.Group(name=qname, child=item)

        if parent.tag == tags.schema:
            self.document.register_group(qname, elm)
        return elm
Exemple #50
0
    def visit_extension_complex_content(self, node, parent):
        """

        Definition::

            <extension
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (
                        (group | all | choice | sequence)?,
                        ((attribute | attributeGroup)*, anyAttribute?)))
            </extension>

        :param node: The XML node
        :type node: lxml.etree._Element
        :param parent: The parent XML node
        :type parent: lxml.etree._Element

        """
        base_name = qname_attr(node, "base")
        base_type = self._get_type(base_name)
        annotation, children = self._pop_annotation(list(node))

        element = None
        attributes = []

        if children:
            child = children[0]
            if child.tag in (tags.group, tags.all, tags.choice, tags.sequence):
                children.pop(0)
                element = self.process(child, node)
            attributes = self._process_attributes(node, children)

        return base_type, element, attributes
Exemple #51
0
    def visit_extension_complex_content(self, node, parent):
        """
            <extension
              base = QName
              id = ID
              {any attributes with non-schema Namespace}...>
            Content: (annotation?, (
                        (group | all | choice | sequence)?,
                        ((attribute | attributeGroup)*, anyAttribute?)))
            </extension>
        """
        base_name = qname_attr(node, 'base')
        try:
            base = self.schema.get_type(base_name)
            children = base._children
        except KeyError:
            children = [xsd_types.UnresolvedType(base_name)]

        for child in node.iterchildren():
            if child.tag == tags.annotation:
                continue

            item = self.process(child, node)

            if child.tag == tags.group:
                children.extend(item)

            elif child.tag in (tags.choice, tags.sequence, tags.all):
                children.extend(item)

            elif child.tag in (tags.attribute,):
                children.append(item)

        return children
Exemple #52
0
def parse_abstract_message(wsdl, xmlelement):
    """Create an AbstractMessage object from a xml element.

    Definition::

        <definitions .... >
            <message name="nmtoken"> *
                <part name="nmtoken" element="qname"? type="qname"?/> *
            </message>
        </definitions>

    :param wsdl: The parent definition instance
    :type wsdl: zeep.wsdl.wsdl.Definition
    :param xmlelement: The XML node
    :type xmlelement: lxml.etree._Element
    :rtype: zeep.wsdl.definitions.AbstractMessage

    """
    tns = wsdl.target_namespace
    message_name = qname_attr(xmlelement, 'name', tns)
    parts = []

    for part in xmlelement.findall('wsdl:part', namespaces=NSMAP):
        part_name = part.get('name')
        part_element = qname_attr(part, 'element', tns)
        part_type = qname_attr(part, 'type', tns)

        try:
            if part_element is not None:
                part_element = wsdl.types.get_element(part_element)
            if part_type is not None:
                part_type = wsdl.types.get_type(part_type)

        except (NamespaceError, LookupError):
            raise IncompleteMessage((
                "The wsdl:message for %r contains an invalid part (%r): "
                "invalid xsd type or elements"
            ) % (message_name.text, part_name))

        part = definitions.MessagePart(part_element, part_type)
        parts.append((part_name, part))

    # Create the object, add the parts and return it
    msg = definitions.AbstractMessage(message_name)
    for part_name, part in parts:
        msg.add_part(part_name, part)
    return msg
Exemple #53
0
def parse_abstract_operation(wsdl, xmlelement):
    """Create an AbstractOperation object from a xml element.

    This is called from the parse_port_type function since the abstract
    operations are part of the port type element.

    Definition::

        <wsdl:operation name="nmtoken">*
           <wsdl:documentation .... /> ?
           <wsdl:input name="nmtoken"? message="qname">?
               <wsdl:documentation .... /> ?
           </wsdl:input>
           <wsdl:output name="nmtoken"? message="qname">?
               <wsdl:documentation .... /> ?
           </wsdl:output>
           <wsdl:fault name="nmtoken" message="qname"> *
               <wsdl:documentation .... /> ?
           </wsdl:fault>
        </wsdl:operation>

    :param wsdl: The parent definition instance
    :type wsdl: zeep.wsdl.wsdl.Definition
    :param xmlelement: The XML node
    :type xmlelement: lxml.etree._Element
    :rtype: zeep.wsdl.definitions.AbstractOperation

    """
    name = xmlelement.get("name")
    kwargs = {"fault_messages": {}}

    for msg_node in xmlelement:
        tag_name = etree.QName(msg_node.tag).localname
        if tag_name not in ("input", "output", "fault"):
            continue

        param_msg = qname_attr(msg_node, "message", wsdl.target_namespace)
        param_name = msg_node.get("name")

        try:
            param_value = wsdl.get("messages", param_msg.text)
        except IndexError:
            return

        if tag_name == "input":
            kwargs["input_message"] = param_value
        elif tag_name == "output":
            kwargs["output_message"] = param_value
        else:
            kwargs["fault_messages"][param_name] = param_value

        wsa_action = msg_node.get(etree.QName(NSMAP["wsam"], "Action"))
        if not wsa_action:
            wsa_action = msg_node.get(etree.QName(NSMAP["wsaw"], "Action"))
        param_value.wsa_action = wsa_action

    kwargs["name"] = name
    kwargs["parameter_order"] = xmlelement.get("parameterOrder")
    return definitions.AbstractOperation(**kwargs)
Exemple #54
0
    def parse_xmlelement(self, xmlelement, schema=None, allow_none=True,
                         context=None, schema_type=None):
        """Consume matching xmlelements and call parse() on each

        :param xmlelement: XML element objects
        :type xmlelement: lxml.etree._Element
        :param schema: The parent XML schema
        :type schema: zeep.xsd.Schema
        :param allow_none: Allow none
        :type allow_none: bool
        :param context: Optional parsing context (for inline schemas)
        :type context: zeep.xsd.context.XmlParserContext
        :param schema_type: The original type (not overriden via xsi:type)
        :type schema_type: zeep.xsd.types.base.Type
        :rtype: dict or None

        """
        xsi_type = qname_attr(xmlelement, xsi_ns('type'))
        xsi_nil = xmlelement.get(xsi_ns('nil'))
        children = list(xmlelement.getchildren())

        # Handle xsi:nil attribute
        if xsi_nil == 'true':
            return None

        # Check if a xsi:type is defined and try to parse the xml according
        # to that type.
        if xsi_type and schema:
            xsd_type = schema.get_type(xsi_type, fail_silently=True)

            # If we were unable to resolve a type for the xsi:type (due to
            # buggy soap servers) then we just return the text or lxml element.
            if not xsd_type:
                logger.debug(
                    "Unable to resolve type for %r, returning raw data",
                    xsi_type.text)

                if xmlelement.text:
                    return xmlelement.text
                return children

            # If the xsd_type is xsd:anyType then we will recurs so ignore
            # that.
            if isinstance(xsd_type, self.__class__):
                return xmlelement.text or None

            return xsd_type.parse_xmlelement(
                xmlelement, schema, context=context)

        # If no xsi:type is set and the element has children then there is
        # not much we can do. Just return the children
        elif children:
            return children

        elif xmlelement.text is not None:
            return self.pythonvalue(xmlelement.text)

        return None
Exemple #55
0
    def parse(cls, definitions, xmlelement):
        """

        Definition::

            <wsdl:binding name="nmtoken" type="qname"> *
                <-- extensibility element (1) --> *
                <wsdl:operation name="nmtoken"> *
                   <-- extensibility element (2) --> *
                   <wsdl:input name="nmtoken"? > ?
                       <-- extensibility element (3) -->
                   </wsdl:input>
                   <wsdl:output name="nmtoken"? > ?
                       <-- extensibility element (4) --> *
                   </wsdl:output>
                   <wsdl:fault name="nmtoken"> *
                       <-- extensibility element (5) --> *
                   </wsdl:fault>
                </wsdl:operation>
            </wsdl:binding>
        """
        name = qname_attr(xmlelement, 'name', definitions.target_namespace)
        port_name = qname_attr(xmlelement, 'type', definitions.target_namespace)

        # The soap:binding element contains the transport method and
        # default style attribute for the operations.
        soap_node = xmlelement.find('soap:binding', namespaces=cls.nsmap)
        transport = soap_node.get('transport')

        supported_transports = [
            'http://schemas.xmlsoap.org/soap/http',
            'http://www.w3.org/2003/05/soap/bindings/HTTP/',
        ]

        if transport not in supported_transports:
            raise NotImplementedError(
                "The binding transport %s is not supported (only soap/http)" % (
                    transport))
        default_style = soap_node.get('style', 'document')

        obj = cls(definitions.wsdl, name, port_name, transport, default_style)
        for node in xmlelement.findall('wsdl:operation', namespaces=cls.nsmap):
            operation = SoapOperation.parse(definitions, node, obj, nsmap=cls.nsmap)
            obj._operation_add(operation)
        return obj
Exemple #56
0
    def process_ref_element(self, node):
        ref = qname_attr(node, 'ref')
        if ref:

            # Some wsdl's reference to xs:schema, we ignore that for now. It
            # might be better in the future to process the actual schema file
            # so that it is handled correctly
            if ref.namespace == 'http://www.w3.org/2001/XMLSchema':
                return
            return xsd_elements.RefElement(node.tag, ref, self.schema)
Exemple #57
0
 def process_reference(self, node, **kwargs):
     ref = qname_attr(node, 'ref')
     if not ref:
         return
     if node.tag == tags.element:
         return xsd_elements.RefElement(node.tag, ref, self.schema, **kwargs)
     if node.tag == tags.attribute:
         return xsd_elements.RefAttribute(node.tag, ref, self.schema, **kwargs)
     if node.tag == tags.group:
         return xsd_elements.RefGroup(node.tag, ref, self.schema, **kwargs)
Exemple #58
0
    def parse_xmlelement(self, xmlelement, schema=None):
        xsi_type = qname_attr(
            xmlelement,
            '{http://www.w3.org/2001/XMLSchema-instance}type')
        if xsi_type and schema:
            xsd_type = schema.get_type(xsi_type)
            return xsd_type.parse_xmlelement(xmlelement, schema)

        if xmlelement.text is None:
            return
        return self.pythonvalue(xmlelement.text)