示例#1
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)
示例#2
0
    def render(self, parent, value, xsd_type=None):
        """Serialize the given value lxml.Element subelements on the parent
        element.

        """
        if not self.elements_nested and not self.attributes:
            return

        # Render attributes
        for name, attribute in self.attributes:
            attr_value = getattr(value, name, None)
            attribute.render(parent, attr_value)

        # Render sub elements
        for name, element in self.elements_nested:
            if isinstance(element, Element) or element.accepts_multiple:
                element_value = getattr(value, name, None)
            else:
                element_value = value

            if isinstance(element, Element):
                element.type.render(parent, element_value)
            else:
                element.render(parent, element_value)

        if xsd_type:
            if xsd_type._xsd_name:
                parent.set(xsi_ns("type"), xsd_type._xsd_name)
            if xsd_type.qname:
                parent.set(xsi_ns("type"), xsd_type.qname)
示例#3
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
示例#4
0
 def render(self, parent, value):
     if isinstance(value, AnyObject):
         value.xsd_type.render(parent, value.value)
         parent.set(xsi_ns('type'), value.xsd_type.qname)
     elif hasattr(value, '_xsd_elm'):
         value._xsd_elm.render(parent, value)
         parent.set(xsi_ns('type'), value._xsd_elm.qname)
     else:
         parent.text = self.xmlvalue(value)
示例#5
0
 def render(self, parent, value, xsd_type=None, render_path=None):
     if isinstance(value, AnyObject):
         if value.xsd_type is None:
             parent.set(xsi_ns('nil'), 'true')
         else:
             value.xsd_type.render(parent, value.value, None, render_path)
             parent.set(xsi_ns('type'), value.xsd_type.qname)
     elif hasattr(value, '_xsd_elm'):
         value._xsd_elm.render(parent, value, render_path)
         parent.set(xsi_ns('type'), value._xsd_elm.qname)
     else:
         parent.text = self.xmlvalue(value)
示例#6
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)
示例#7
0
    def render(self, parent, value, xsd_type=None):
        """Serialize the given value lxml.Element subelements on the parent
        element.

        """
        if not self.elements_nested and not self.attributes:
            return

        # Render attributes
        for name, attribute in self.attributes:
            attr_value = getattr(value, name, None)
            attribute.render(parent, attr_value)

        # Render sub elements
        for name, element in self.elements_nested:
            if isinstance(element, Element) or element.accepts_multiple:
                element_value = getattr(value, name, None)
            else:
                element_value = value

            if isinstance(element, Element):
                element.type.render(parent, element_value)
            else:
                element.render(parent, element_value)

        if xsd_type and xsd_type._xsd_name:
            parent.set(xsi_ns('type'), xsd_type._xsd_name)
示例#8
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
示例#9
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._has_schema_document(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
示例#10
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)
示例#11
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
示例#12
0
    def render(
        self,
        node: etree._Element,
        value: typing.Union[list, dict, CompoundValue],
        xsd_type: "ComplexType" = None,
        render_path=None,
    ) -> None:
        assert xsd_type is None

        if isinstance(value, AnyObject):
            if value.xsd_type is None:
                node.set(xsi_ns("nil"), "true")
            else:
                value.xsd_type.render(node, value.value, None, render_path)
                node.set(xsi_ns("type"), value.xsd_type.qname)
        elif isinstance(value, CompoundValue):
            value._xsd_elm.render(node, value, render_path)
            node.set(xsi_ns("type"), value._xsd_elm.qname)
        else:
            node.text = self.xmlvalue(value)
示例#13
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'))
        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 lxml element.
            if not xsd_type:
                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
示例#14
0
文件: simple.py 项目: leomarp/Test2
    def render(
        self,
        node: etree._Element,
        value: typing.Union[list, dict, CompoundValue],
        xsd_type: "ComplexType" = None,
        render_path=None,
    ) -> None:
        assert xsd_type is None

        if value is Nil:
            node.set(xsi_ns("nil"), "true")
            return
        node.text = self.xmlvalue(value)
示例#15
0
    def render(self, parent, value, xsd_type=None, render_path=None):
        """Serialize the given value lxml.Element subelements on the parent
        element.

        """
        if not render_path:
            render_path = [self.name]

        if not self.elements_nested and not self.attributes:
            return

        # Render attributes
        for name, attribute in self.attributes:
            attr_value = value[name] if name in value else NotSet
            child_path = render_path + [name]
            attribute.render(parent, attr_value, child_path)

        # Render sub elements
        for name, element in self.elements_nested:
            if isinstance(element, Element) or element.accepts_multiple:
                element_value = value[name] if name in value else NotSet
                child_path = render_path + [name]
            else:
                element_value = value
                child_path = list(render_path)

            if element_value is SkipValue:
                continue

            if isinstance(element, Element):
                element.type.render(parent, element_value, None, child_path)
            else:
                element.render(parent, element_value, child_path)

        if xsd_type:
            if xsd_type._xsd_name:
                parent.set(xsi_ns('type'), xsd_type._xsd_name)
            if xsd_type.qname:
                parent.set(xsi_ns('type'), xsd_type.qname)
示例#16
0
    def _render_value_item(self, parent, value, render_path):
        """Render the value on the parent lxml.Element"""

        if value is Nil:
            elm = etree.SubElement(parent, self.qname)
            elm.set(xsi_ns('nil'), 'true')
            return

        if value is None or value is NotSet:
            if self.is_optional:
                return

            elm = etree.SubElement(parent, self.qname)
            if self.nillable:
                elm.set(xsi_ns('nil'), 'true')
            return

        node = etree.SubElement(parent, self.qname)
        xsd_type = getattr(value, '_xsd_type', self.type)

        if xsd_type != self.type:
            return value._xsd_type.render(node, value, xsd_type, render_path)
        return self.type.render(node, value, None, render_path)
示例#17
0
    def _render_value_item(self, parent, value, render_path):
        """Render the value on the parent lxml.Element"""

        if value is Nil:
            elm = etree.SubElement(parent, self.qname)
            elm.set(xsi_ns('nil'), 'true')
            return

        if value is None or value is NotSet:
            if self.is_optional:
                return

            elm = etree.SubElement(parent, self.qname)
            if self.nillable:
                elm.set(xsi_ns('nil'), 'true')
            return

        node = etree.SubElement(parent, self.qname)
        xsd_type = getattr(value, '_xsd_type', self.type)

        if xsd_type != self.type:
            return value._xsd_type.render(node, value, xsd_type, render_path)
        return self.type.render(node, value, None, render_path)
示例#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.

        """
        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)
示例#19
0
    def render(self, parent, value):
        assert parent is not None
        if self.accepts_multiple and isinstance(value, list):
            from zeep.xsd import SimpleType

            if isinstance(self.restrict, SimpleType):
                for val in value:
                    node = etree.SubElement(parent, 'item')
                    node.set(xsi_ns('type'), self.restrict.qname)
                    self._render_value_item(node, val)
            else:
                for val in value:
                    self._render_value_item(parent, val)
        else:
            self._render_value_item(parent, value)
示例#20
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)
示例#21
0
    def parse(self, xmlelement, schema, context=None):
        if self.process_contents == 'skip':
            return xmlelement

        qname = etree.QName(xmlelement.tag)
        for context_schema in context.schemas:
            if qname.namespace in context_schema._schemas:
                schema = context_schema
                break

        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)

        try:
            element = schema.get_element(xmlelement.tag)
            return element.parse(xmlelement, schema, context=context)
        except (exceptions.NamespaceError, exceptions.LookupError):
            return xmlelement
示例#22
0
    def render(self, parent, value):
        assert parent is not None
        if self.accepts_multiple and isinstance(value, list):
            from zeep.xsd import SimpleType

            if isinstance(self.restrict, SimpleType):
                for val in value:
                    node = etree.SubElement(parent, 'item')
                    node.set(xsi_ns('type'), self.restrict.qname)
                    self._render_value_item(node, val)
            elif self.restrict:
                for val in value:
                    node = etree.SubElement(parent, self.restrict.name)
                    # node.set(xsi_ns('type'), self.restrict.qname)
                    self._render_value_item(node, val)
            else:
                for val in value:
                    self._render_value_item(parent, val)
        else:
            self._render_value_item(parent, value)
示例#23
0
    def render(self, parent, value, render_path=None):
        assert parent is not None
        self.validate(value, render_path)

        if self.accepts_multiple and isinstance(value, list):
            from zeep.xsd import AnySimpleType

            if isinstance(self.restrict, AnySimpleType):
                for val in value:
                    node = etree.SubElement(parent, "item")
                    node.set(xsi_ns("type"), self.restrict.qname)
                    self._render_value_item(node, val, render_path)
            elif self.restrict:
                for val in value:
                    node = etree.SubElement(parent, self.restrict.name)
                    # node.set(xsi_ns('type'), self.restrict.qname)
                    self._render_value_item(node, val, render_path)
            else:
                for val in value:
                    self._render_value_item(parent, val, render_path)
        else:
            self._render_value_item(parent, value, render_path)
示例#24
0
    def parse_xmlelement(
        self,
        xmlelement: etree._Element,
        schema: "Schema" = None,
        allow_none: bool = True,
        context: XmlParserContext = None,
        schema_type: "Type" = None,
    ) -> typing.Optional[typing.Union[str, CompoundValue,
                                      typing.List[etree._Element]]]:
        """Try to parse the xml element and return a value for it.

        There is a big chance that we cannot parse this value since it is an
        Any. In that case we just return the raw lxml Element nodes.

        :param xmlelement: XML element objects
        :param schema: The parent XML schema
        :param allow_none: Allow none
        :param context: Optional parsing context (for inline schemas)
        :param schema_type: The original type (not overriden via xsi:type)

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

        # 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 self.pythonvalue(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 self.pythonvalue(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
示例#25
0
    def render(self, parent, value, xsd_type=None, render_path=None):
        """Serialize the given value lxml.Element subelements on the parent
        element.

        :type parent: lxml.etree._Element
        :type value: Union[list, dict, zeep.xsd.valueobjects.CompoundValue]
        :type xsd_type: zeep.xsd.types.base.Type
        :param render_path: list

        """
        if not render_path:
            render_path = [self.name]

        if not self.elements_nested and not self.attributes:
            return

        # TODO: Implement test case for this
        if value is None:
            value = {}

        if isinstance(value, ArrayValue):
            value = value.as_value_object()

        # Render attributes
        for name, attribute in self.attributes:
            import sys
            if sys.version_info < (3, 4):
                if isinstance(value, str) or isinstance(value, unicode):
                    attr_value = NotSet
                else:
                    attr_value = value[name] if name in value else NotSet
            else:
                if isinstance(value, str):
                    attr_value = NotSet
                else:
                    attr_value = value[name] if name in value else NotSet
            child_path = render_path + [name]
            attribute.render(parent, attr_value, child_path)

        if (len(self.elements_nested) == 1
                and isinstance(value, self.accepted_types)
                and not isinstance(value, (list, dict, CompoundValue))):
            element = self.elements_nested[0][1]
            element.type.render(parent, value, None, child_path)
            return

        # Render sub elements
        for name, element in self.elements_nested:
            if isinstance(element, Element) or element.accepts_multiple:
                element_value = value[name] if name in value else NotSet
                child_path = render_path + [name]
            else:
                element_value = value
                child_path = list(render_path)

            # We want to explicitly skip this sub-element
            if element_value is SkipValue:
                continue

            if isinstance(element, Element):
                element.type.render(parent, element_value, None, child_path)
            else:
                element.render(parent, element_value, child_path)

        if xsd_type:
            if xsd_type._xsd_name:
                parent.set(xsi_ns("type"), xsd_type._xsd_name)
            if xsd_type.qname:
                parent.set(xsi_ns("type"), xsd_type.qname)
示例#26
0
 def render(self, parent, value, xsd_type=None, render_path=None):
     if value is Nil:
         parent.set(xsi_ns("nil"), "true")
         return
     parent.text = self.xmlvalue(value)
示例#27
0
文件: complex.py 项目: leomarp/Test2
    def render(
        self,
        node: etree._Element,
        value: typing.Union[list, dict, CompoundValue],
        xsd_type: "ComplexType" = None,
        render_path=None,
    ) -> None:
        """Serialize the given value lxml.Element subelements on the node
        element.

        :param render_path: list

        """
        if not render_path:
            render_path = [self.name]

        if not self.elements_nested and not self.attributes:
            return

        # TODO: Implement test case for this
        if value is None:
            value = {}

        if isinstance(value, ArrayValue):
            value = value.as_value_object()

        # Render attributes
        for name, attribute in self.attributes:
            attr_value = value[name] if name in value else NotSet
            child_path = render_path + [name]
            attribute.render(node, attr_value, child_path)

        if (
            len(self.elements_nested) == 1
            and isinstance(value, tuple(self.accepted_types))
            and not isinstance(value, (list, dict, CompoundValue))
        ):
            element = self.elements_nested[0][1]
            element.type.render(node, value, None, child_path)
            return

        # Render sub elements
        for name, element in self.elements_nested:
            if isinstance(element, Element) or element.accepts_multiple:
                element_value = value[name] if name in value else NotSet
                child_path = render_path + [name]
            else:
                element_value = value
                child_path = list(render_path)

            # We want to explicitly skip this sub-element
            if element_value is SkipValue:
                continue

            if isinstance(element, Element):
                element.type.render(node, element_value, None, child_path)
            else:
                element.render(node, element_value, child_path)

        if xsd_type:
            if xsd_type._xsd_name:
                node.set(xsi_ns("type"), xsd_type._xsd_name)
            if xsd_type.qname:
                node.set(xsi_ns("type"), xsd_type.qname)
示例#28
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
示例#29
0
    def render(self, parent, value, xsd_type=None, render_path=None):
        """Serialize the given value lxml.Element subelements on the parent
        element.

        :type parent: lxml.etree._Element
        :type value: Union[list, dict, zeep.xsd.valueobjects.CompoundValue]
        :type xsd_type: zeep.xsd.types.base.Type
        :param render_path: list

        """
        if not render_path:
            render_path = [self.name]

        if not self.elements_nested and not self.attributes:
            return

        # TODO: Implement test case for this
        if value is None:
            value = {}

        if isinstance(value, ArrayValue):
            value = value.as_value_object()

        # Render attributes
        for name, attribute in self.attributes:
            attr_value = value[name] if name in value else NotSet
            child_path = render_path + [name]
            attribute.render(parent, attr_value, child_path)

        if (
            len(self.elements_nested) == 1
            and isinstance(value, self.accepted_types)
            and not isinstance(value, (list, dict, CompoundValue))
        ):
            element = self.elements_nested[0][1]
            element.type.render(parent, value, None, child_path)
            return

        # Render sub elements
        for name, element in self.elements_nested:
            if isinstance(element, Element) or element.accepts_multiple:
                element_value = value[name] if name in value else NotSet
                child_path = render_path + [name]
            else:
                element_value = value
                child_path = list(render_path)

            # We want to explicitly skip this sub-element
            if element_value is SkipValue:
                continue

            if isinstance(element, Element):
                element.type.render(parent, element_value, None, child_path)
            else:
                element.render(parent, element_value, child_path)

        if xsd_type:
            if xsd_type._xsd_name:
                parent.set(xsi_ns('type'), xsd_type._xsd_name)
            if xsd_type.qname:
                parent.set(xsi_ns('type'), xsd_type.qname)
示例#30
0
 def render(self, parent, value):
     if isinstance(value, AnyObject):
         value.xsd_type.render(parent, value.value)
         parent.set(xsi_ns('type'), value.xsd_type.qname)
     else:
         parent.text = self.xmlvalue(value)
示例#31
0
 def render(self, parent, value, xsd_type=None, render_path=None):
     if value is Nil:
         parent.set(xsi_ns('nil'), 'true')
         return
     parent.text = self.xmlvalue(value)
示例#32
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

        """
        # If this is an empty complexType (<xsd:complexType name="x"/>)
        if not self.attributes and not self.elements:
            return None

        attributes = xmlelement.attrib
        init_kwargs = OrderedDict()

        if allow_none and xmlelement.get(xsi_ns('nil')) == 'true':
            return None

        # If this complexType extends a simpleType then we have no nested
        # elements. Parse it directly via the type object. This is the case
        # for xsd:simpleContent
        if isinstance(self._element, Element) and isinstance(
                self._element.type, AnySimpleType):
            name, element = self.elements_nested[0]
            init_kwargs[name] = element.type.parse_xmlelement(xmlelement,
                                                              schema,
                                                              name,
                                                              context=context)
        else:
            elements = deque(xmlelement.iterchildren())
            if allow_none and len(elements) == 0 and len(attributes) == 0:
                return

            # Parse elements. These are always indicator elements (all, choice,
            # group, sequence)
            assert len(self.elements_nested) < 2
            for name, element in self.elements_nested:
                try:
                    result = element.parse_xmlelements(elements,
                                                       schema,
                                                       name,
                                                       context=context)
                    if result:
                        init_kwargs.update(result)
                except UnexpectedElementError as exc:
                    raise XMLParseError(exc.message)

            # Check if all children are consumed (parsed)
            if elements:
                if schema.settings.strict:
                    raise XMLParseError("Unexpected element %r" %
                                        elements[0].tag)
                else:
                    init_kwargs["_raw_elements"] = elements

        # Parse attributes
        if attributes:
            attributes = copy.copy(attributes)
            for name, attribute in self.attributes:
                if attribute.name:
                    if attribute.qname.text in attributes:
                        value = attributes.pop(attribute.qname.text)
                        init_kwargs[name] = attribute.parse(value)
                else:
                    init_kwargs[name] = attribute.parse(attributes)

        value = self._value_class(**init_kwargs)
        schema_type = schema_type or self
        if schema_type and getattr(schema_type, "_array_type", None):
            value = schema_type._array_class.from_value_object(value)
        return value