[tryton-debian-vcs] python-zeep branch debian updated. debian/0.23.0-1-3-gc25d68a

Mathias Behrle tryton-debian-vcs at alioth.debian.org
Tue Jan 24 09:54:58 UTC 2017


The following commit has been merged in the debian branch:
https://alioth.debian.org/plugins/scmgit/cgi-bin/gitweb.cgi/?p=tryton/python-zeep.git;a=commitdiff;h=debian/0.23.0-1-3-gc25d68a

commit c25d68aac10d5bf8ab4f9ddee428482c06d55b17
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Tue Jan 24 10:54:52 2017 +0100

    Put a minimal version constraint for python-six to pull from jessie-backports instead of jessie.

diff --git a/debian/control b/debian/control
index 5163435..99cbd52 100644
--- a/debian/control
+++ b/debian/control
@@ -23,7 +23,7 @@ Build-Depends:
  python-requests,
  python-requests-mock,
  python-setuptools,
- python-six,
+ python-six (>= 1.9.0-3~),
  python-tz,
  python3,
  python3-appdirs,
@@ -60,7 +60,7 @@ Depends:
  python-pkg-resources,
  python-requests,
  python-setuptools,
- python-six,
+ python-six (>= 1.9.0-3~),
  python-tz,
  ${misc:Depends},
  ${python:Depends},
commit 76a9dacf0b9241ab02265039ecc32669a027998e
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Wed Dec 21 22:53:13 2016 +0100

    Remove 01-add-missing-xsd-files.patch, went upstream.

diff --git a/debian/patches/01-add-missing-xsd-files.patch b/debian/patches/01-add-missing-xsd-files.patch
deleted file mode 100644
index c615cae..0000000
--- a/debian/patches/01-add-missing-xsd-files.patch
+++ /dev/null
@@ -1,1007 +0,0 @@
-Description: Add missing test files
- Those files needed to run the tests are in the git repository,
- but not in the tarball on pypi.
-Author: Mathias Behrle <mbehrle at debian.org>
-Bug-Debian: https://bugs.debian.org/834485
-Bug: https://github.com/mvantellingen/python-zeep/issues/27
-Last-Update: 2016-12-06
-
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ python-zeep/tests/wsdl_files/soap-enc.xsd	2016-12-06 18:34:15.926748461 +0100
-@@ -0,0 +1,535 @@
-+<?xml version='1.0' encoding='UTF-8' ?>
-+
-+<!-- Schema for the SOAP/1.1 encoding
-+
-+Portions © 2001 DevelopMentor. 
-+© 2001 W3C (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved.  
-+ 
-+This document is governed by the W3C Software License [1] as described in the FAQ [2].
-+[1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
-+[2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD 
-+By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
-+
-+Permission to use, copy, modify, and distribute this software and its documentation, with or without modification,  for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make:
-+
-+1.  The full text of this NOTICE in a location viewable to users of the redistributed or derivative work. 
-+
-+2.  Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, a short notice of the following form (hypertext is preferred, text is permitted) should be used within the body of any redistributed or derivative code: "Copyright © 2001 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/" 
-+
-+3.  Notice of any changes or modifications to the W3C files, including the date changes were made. (We recommend you provide URIs to the location from which the code is derived.)   
-+
-+Original W3C files; http://www.w3.org/2001/06/soap-encoding
-+Changes made: 
-+     - reverted namespace to http://schemas.xmlsoap.org/soap/encoding/
-+     - reverted root to only allow 0 and 1 as lexical values
-+	 - removed default value from root attribute declaration
-+
-+THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
-+
-+COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
-+
-+The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software without specific, written prior permission. Title to copyright in this software and any associated documentation will at all times remain with copyright holders.
-+
-+-->
-+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
-+           xmlns:tns="http://schemas.xmlsoap.org/soap/encoding/"
-+           targetNamespace="http://schemas.xmlsoap.org/soap/encoding/" >
-+        
-+ <xs:attribute name="root" >
-+   <xs:annotation>
-+     <xs:documentation>
-+	   'root' can be used to distinguish serialization roots from other
-+       elements that are present in a serialization but are not roots of
-+       a serialized value graph 
-+	 </xs:documentation>
-+   </xs:annotation>
-+   <xs:simpleType>
-+     <xs:restriction base='xs:boolean'>
-+	   <xs:pattern value='0|1' />
-+	 </xs:restriction>
-+   </xs:simpleType>
-+ </xs:attribute>
-+
-+  <xs:attributeGroup name="commonAttributes" >
-+    <xs:annotation>
-+	  <xs:documentation>
-+	    Attributes common to all elements that function as accessors or 
-+        represent independent (multi-ref) values.  The href attribute is
-+        intended to be used in a manner like CONREF.  That is, the element
-+        content should be empty iff the href attribute appears
-+	  </xs:documentation>
-+	</xs:annotation>
-+    <xs:attribute name="id" type="xs:ID" />
-+    <xs:attribute name="href" type="xs:anyURI" />
-+    <xs:anyAttribute namespace="##other" processContents="lax" />
-+  </xs:attributeGroup>
-+
-+  <!-- Global Attributes.  The following attributes are intended to be usable via qualified attribute names on any complex type referencing them. -->
-+       
-+  <!-- Array attributes. Needed to give the type and dimensions of an array's contents, and the offset for partially-transmitted arrays. -->
-+   
-+  <xs:simpleType name="arrayCoordinate" >
-+    <xs:restriction base="xs:string" />
-+  </xs:simpleType>
-+          
-+  <xs:attribute name="arrayType" type="xs:string" />
-+  <xs:attribute name="offset" type="tns:arrayCoordinate" />
-+  
-+  <xs:attributeGroup name="arrayAttributes" >
-+    <xs:attribute ref="tns:arrayType" />
-+    <xs:attribute ref="tns:offset" />
-+  </xs:attributeGroup>    
-+  
-+  <xs:attribute name="position" type="tns:arrayCoordinate" /> 
-+  
-+  <xs:attributeGroup name="arrayMemberAttributes" >
-+    <xs:attribute ref="tns:position" />
-+  </xs:attributeGroup>    
-+
-+  <xs:group name="Array" >
-+    <xs:sequence>
-+      <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
-+	</xs:sequence>
-+  </xs:group>
-+
-+  <xs:element name="Array" type="tns:Array" />
-+  <xs:complexType name="Array" >
-+    <xs:annotation>
-+	  <xs:documentation>
-+	   'Array' is a complex type for accessors identified by position 
-+	  </xs:documentation>
-+	</xs:annotation>
-+    <xs:group ref="tns:Array" minOccurs="0" />
-+    <xs:attributeGroup ref="tns:arrayAttributes" />
-+    <xs:attributeGroup ref="tns:commonAttributes" />
-+  </xs:complexType> 
-+
-+  <!-- 'Struct' is a complex type for accessors identified by name. 
-+       Constraint: No element may be have the same name as any other,
-+       nor may any element have a maxOccurs > 1. -->
-+   
-+  <xs:element name="Struct" type="tns:Struct" />
-+
-+  <xs:group name="Struct" >
-+    <xs:sequence>
-+      <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
-+	</xs:sequence>
-+  </xs:group>
-+
-+  <xs:complexType name="Struct" >
-+    <xs:group ref="tns:Struct" minOccurs="0" />
-+    <xs:attributeGroup ref="tns:commonAttributes"/>
-+  </xs:complexType> 
-+
-+  <!-- 'Base64' can be used to serialize binary data using base64 encoding
-+       as defined in RFC2045 but without the MIME line length limitation. -->
-+
-+  <xs:simpleType name="base64" >
-+    <xs:restriction base="xs:base64Binary" />
-+  </xs:simpleType>
-+
-+ <!-- Element declarations corresponding to each of the simple types in the 
-+      XML Schemas Specification. -->
-+
-+  <xs:element name="duration" type="tns:duration" />
-+  <xs:complexType name="duration" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:duration" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="dateTime" type="tns:dateTime" />
-+  <xs:complexType name="dateTime" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:dateTime" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+
-+
-+  <xs:element name="NOTATION" type="tns:NOTATION" />
-+  <xs:complexType name="NOTATION" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:QName" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+  
-+
-+  <xs:element name="time" type="tns:time" />
-+  <xs:complexType name="time" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:time" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="date" type="tns:date" />
-+  <xs:complexType name="date" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:date" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="gYearMonth" type="tns:gYearMonth" />
-+  <xs:complexType name="gYearMonth" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:gYearMonth" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="gYear" type="tns:gYear" />
-+  <xs:complexType name="gYear" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:gYear" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="gMonthDay" type="tns:gMonthDay" />
-+  <xs:complexType name="gMonthDay" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:gMonthDay" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="gDay" type="tns:gDay" />
-+  <xs:complexType name="gDay" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:gDay" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="gMonth" type="tns:gMonth" />
-+  <xs:complexType name="gMonth" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:gMonth" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+  
-+  <xs:element name="boolean" type="tns:boolean" />
-+  <xs:complexType name="boolean" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:boolean" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="base64Binary" type="tns:base64Binary" />
-+  <xs:complexType name="base64Binary" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:base64Binary" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="hexBinary" type="tns:hexBinary" />
-+  <xs:complexType name="hexBinary" >
-+    <xs:simpleContent>
-+     <xs:extension base="xs:hexBinary" >
-+       <xs:attributeGroup ref="tns:commonAttributes" />
-+     </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="float" type="tns:float" />
-+  <xs:complexType name="float" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:float" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="double" type="tns:double" />
-+  <xs:complexType name="double" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:double" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="anyURI" type="tns:anyURI" />
-+  <xs:complexType name="anyURI" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:anyURI" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="QName" type="tns:QName" />
-+  <xs:complexType name="QName" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:QName" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  
-+  <xs:element name="string" type="tns:string" />
-+  <xs:complexType name="string" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:string" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="normalizedString" type="tns:normalizedString" />
-+  <xs:complexType name="normalizedString" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:normalizedString" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="token" type="tns:token" />
-+  <xs:complexType name="token" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:token" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="language" type="tns:language" />
-+  <xs:complexType name="language" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:language" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="Name" type="tns:Name" />
-+  <xs:complexType name="Name" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:Name" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="NMTOKEN" type="tns:NMTOKEN" />
-+  <xs:complexType name="NMTOKEN" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:NMTOKEN" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="NCName" type="tns:NCName" />
-+  <xs:complexType name="NCName" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:NCName" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="NMTOKENS" type="tns:NMTOKENS" />
-+  <xs:complexType name="NMTOKENS" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:NMTOKENS" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="ID" type="tns:ID" />
-+  <xs:complexType name="ID" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:ID" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="IDREF" type="tns:IDREF" />
-+  <xs:complexType name="IDREF" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:IDREF" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="ENTITY" type="tns:ENTITY" />
-+  <xs:complexType name="ENTITY" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:ENTITY" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="IDREFS" type="tns:IDREFS" />
-+  <xs:complexType name="IDREFS" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:IDREFS" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="ENTITIES" type="tns:ENTITIES" />
-+  <xs:complexType name="ENTITIES" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:ENTITIES" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="decimal" type="tns:decimal" />
-+  <xs:complexType name="decimal" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:decimal" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="integer" type="tns:integer" />
-+  <xs:complexType name="integer" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:integer" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="nonPositiveInteger" type="tns:nonPositiveInteger" />
-+  <xs:complexType name="nonPositiveInteger" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:nonPositiveInteger" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="negativeInteger" type="tns:negativeInteger" />
-+  <xs:complexType name="negativeInteger" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:negativeInteger" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="long" type="tns:long" />
-+  <xs:complexType name="long" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:long" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="int" type="tns:int" />
-+  <xs:complexType name="int" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:int" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="short" type="tns:short" />
-+  <xs:complexType name="short" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:short" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="byte" type="tns:byte" />
-+  <xs:complexType name="byte" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:byte" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="nonNegativeInteger" type="tns:nonNegativeInteger" />
-+  <xs:complexType name="nonNegativeInteger" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:nonNegativeInteger" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="unsignedLong" type="tns:unsignedLong" />
-+  <xs:complexType name="unsignedLong" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:unsignedLong" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="unsignedInt" type="tns:unsignedInt" />
-+  <xs:complexType name="unsignedInt" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:unsignedInt" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="unsignedShort" type="tns:unsignedShort" />
-+  <xs:complexType name="unsignedShort" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:unsignedShort" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="unsignedByte" type="tns:unsignedByte" />
-+  <xs:complexType name="unsignedByte" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:unsignedByte" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="positiveInteger" type="tns:positiveInteger" />
-+  <xs:complexType name="positiveInteger" >
-+    <xs:simpleContent>
-+      <xs:extension base="xs:positiveInteger" >
-+        <xs:attributeGroup ref="tns:commonAttributes" />
-+      </xs:extension>
-+    </xs:simpleContent>
-+  </xs:complexType>
-+
-+  <xs:element name="anyType" />
-+</xs:schema>
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ python-zeep/tests/wsdl_files/test_import_2.xsd	2016-12-06 18:34:15.926748461 +0100
-@@ -0,0 +1,60 @@
-+<schema xmlns="http://www.w3.org/2001/XMLSchema" 
-+        targetNamespace="http://example.com/stockquote.xsd"
-+        xmlns:tns="http://example.com/stockquote.xsd" >
-+  <complexType name="Address">
-+    <sequence>
-+      <element minOccurs="0" maxOccurs="1" name="NameFirst" type="string"/>
-+      <element minOccurs="0" maxOccurs="1" name="NameLast" type="string"/>
-+      <element minOccurs="0" maxOccurs="1" name="Email" type="string"/>
-+    </sequence>
-+  </complexType>
-+  <element name="Fault1">
-+    <complexType>
-+      <sequence>
-+        <element name="message" type="string"/>
-+      </sequence>
-+    </complexType>
-+  </element>
-+  <element name="Fault2">
-+    <complexType>
-+      <sequence>
-+        <element name="message" type="string"/>
-+      </sequence>
-+    </complexType>
-+  </element>
-+  <element name="TradePriceRequest">
-+    <complexType>
-+      <all>
-+        <element name="tickerSymbol" type="string"/>
-+        <element name="account" type="tns:account" minOccurs="0" />
-+        <element ref="tns:country"/>
-+      </all>
-+    </complexType>
-+  </element>
-+  <element name="TradePrice">
-+    <complexType>
-+      <all>
-+        <element name="price" type="float"/>
-+      </all>
-+    </complexType>
-+  </element>
-+  <complexType name="account">
-+    <sequence>
-+      <element name="id" type="int"/>
-+      <element name="user" type="string"/>
-+    </sequence>
-+  </complexType>
-+  <complexType name="country">
-+      <sequence>
-+        <element name="code" type="string"/>
-+      </sequence>
-+  </complexType>
-+  <element name="country">
-+    <complexType>
-+      <sequence>
-+        <element name="name" type="string"/>
-+        <element name="code" type="string"/>
-+      </sequence>
-+    </complexType>
-+  </element>
-+</schema>
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ python-zeep/tests/wsdl_files/xmldsig-core-schema.xsd	2016-12-06 18:34:15.926748461 +0100
-@@ -0,0 +1,309 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+
-+<!-- Schema for XML Signatures
-+    http://www.w3.org/2000/09/xmldsig#
-+    $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
-+
-+    Copyright 2001 The Internet Society and W3C (Massachusetts Institute
-+    of Technology, Institut National de Recherche en Informatique et en
-+    Automatique, Keio University). All Rights Reserved.
-+    http://www.w3.org/Consortium/Legal/
-+
-+    This document is governed by the W3C Software License [1] as described
-+    in the FAQ [2].
-+
-+    [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
-+    [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
-+-->
-+
-+
-+<schema xmlns="http://www.w3.org/2001/XMLSchema"
-+        xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
-+        targetNamespace="http://www.w3.org/2000/09/xmldsig#"
-+        version="0.1" elementFormDefault="qualified"> 
-+
-+<!-- Basic Types Defined for Signatures -->
-+
-+<simpleType name="CryptoBinary">
-+  <restriction base="base64Binary">
-+  </restriction>
-+</simpleType>
-+
-+<!-- Start Signature -->
-+
-+<element name="Signature" type="ds:SignatureType"/>
-+<complexType name="SignatureType">
-+  <sequence> 
-+    <element ref="ds:SignedInfo"/> 
-+    <element ref="ds:SignatureValue"/> 
-+    <element ref="ds:KeyInfo" minOccurs="0"/> 
-+    <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/> 
-+  </sequence>  
-+  <attribute name="Id" type="ID" use="optional"/>
-+</complexType>
-+
-+  <element name="SignatureValue" type="ds:SignatureValueType"/> 
-+  <complexType name="SignatureValueType">
-+    <simpleContent>
-+      <extension base="base64Binary">
-+        <attribute name="Id" type="ID" use="optional"/>
-+      </extension>
-+    </simpleContent>
-+  </complexType>
-+
-+<!-- Start SignedInfo -->
-+
-+<element name="SignedInfo" type="ds:SignedInfoType"/>
-+<complexType name="SignedInfoType">
-+  <sequence> 
-+    <element ref="ds:CanonicalizationMethod"/> 
-+    <element ref="ds:SignatureMethod"/> 
-+    <element ref="ds:Reference" maxOccurs="unbounded"/> 
-+  </sequence>  
-+  <attribute name="Id" type="ID" use="optional"/> 
-+</complexType>
-+
-+  <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/> 
-+  <complexType name="CanonicalizationMethodType" mixed="true">
-+    <sequence>
-+      <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
-+      <!-- (0,unbounded) elements from (1,1) namespace -->
-+    </sequence>
-+    <attribute name="Algorithm" type="anyURI" use="required"/> 
-+  </complexType>
-+
-+  <element name="SignatureMethod" type="ds:SignatureMethodType"/>
-+  <complexType name="SignatureMethodType" mixed="true">
-+    <sequence>
-+      <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
-+      <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
-+      <!-- (0,unbounded) elements from (1,1) external namespace -->
-+    </sequence>
-+    <attribute name="Algorithm" type="anyURI" use="required"/> 
-+  </complexType>
-+
-+<!-- Start Reference -->
-+
-+<element name="Reference" type="ds:ReferenceType"/>
-+<complexType name="ReferenceType">
-+  <sequence> 
-+    <element ref="ds:Transforms" minOccurs="0"/> 
-+    <element ref="ds:DigestMethod"/> 
-+    <element ref="ds:DigestValue"/> 
-+  </sequence>
-+  <attribute name="Id" type="ID" use="optional"/> 
-+  <attribute name="URI" type="anyURI" use="optional"/> 
-+  <attribute name="Type" type="anyURI" use="optional"/> 
-+</complexType>
-+
-+  <element name="Transforms" type="ds:TransformsType"/>
-+  <complexType name="TransformsType">
-+    <sequence>
-+      <element ref="ds:Transform" maxOccurs="unbounded"/>  
-+    </sequence>
-+  </complexType>
-+
-+  <element name="Transform" type="ds:TransformType"/>
-+  <complexType name="TransformType" mixed="true">
-+    <choice minOccurs="0" maxOccurs="unbounded"> 
-+      <any namespace="##other" processContents="lax"/>
-+      <!-- (1,1) elements from (0,unbounded) namespaces -->
-+      <element name="XPath" type="string"/> 
-+    </choice>
-+    <attribute name="Algorithm" type="anyURI" use="required"/> 
-+  </complexType>
-+
-+<!-- End Reference -->
-+
-+<element name="DigestMethod" type="ds:DigestMethodType"/>
-+<complexType name="DigestMethodType" mixed="true"> 
-+  <sequence>
-+    <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
-+  </sequence>    
-+  <attribute name="Algorithm" type="anyURI" use="required"/> 
-+</complexType>
-+
-+<element name="DigestValue" type="ds:DigestValueType"/>
-+<simpleType name="DigestValueType">
-+  <restriction base="base64Binary"/>
-+</simpleType>
-+
-+<!-- End SignedInfo -->
-+
-+<!-- Start KeyInfo -->
-+
-+<element name="KeyInfo" type="ds:KeyInfoType"/> 
-+<complexType name="KeyInfoType" mixed="true">
-+  <choice maxOccurs="unbounded">     
-+    <element ref="ds:KeyName"/> 
-+    <element ref="ds:KeyValue"/> 
-+    <element ref="ds:RetrievalMethod"/> 
-+    <element ref="ds:X509Data"/> 
-+    <element ref="ds:PGPData"/> 
-+    <element ref="ds:SPKIData"/>
-+    <element ref="ds:MgmtData"/>
-+    <any processContents="lax" namespace="##other"/>
-+    <!-- (1,1) elements from (0,unbounded) namespaces -->
-+  </choice>
-+  <attribute name="Id" type="ID" use="optional"/> 
-+</complexType>
-+
-+  <element name="KeyName" type="string"/>
-+  <element name="MgmtData" type="string"/>
-+
-+  <element name="KeyValue" type="ds:KeyValueType"/> 
-+  <complexType name="KeyValueType" mixed="true">
-+   <choice>
-+     <element ref="ds:DSAKeyValue"/>
-+     <element ref="ds:RSAKeyValue"/>
-+     <any namespace="##other" processContents="lax"/>
-+   </choice>
-+  </complexType>
-+
-+  <element name="RetrievalMethod" type="ds:RetrievalMethodType"/> 
-+  <complexType name="RetrievalMethodType">
-+    <sequence>
-+      <element ref="ds:Transforms" minOccurs="0"/> 
-+    </sequence>  
-+    <attribute name="URI" type="anyURI"/>
-+    <attribute name="Type" type="anyURI" use="optional"/>
-+  </complexType>
-+
-+<!-- Start X509Data -->
-+
-+<element name="X509Data" type="ds:X509DataType"/> 
-+<complexType name="X509DataType">
-+  <sequence maxOccurs="unbounded">
-+    <choice>
-+      <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
-+      <element name="X509SKI" type="base64Binary"/>
-+      <element name="X509SubjectName" type="string"/>
-+      <element name="X509Certificate" type="base64Binary"/>
-+      <element name="X509CRL" type="base64Binary"/>
-+      <any namespace="##other" processContents="lax"/>
-+    </choice>
-+  </sequence>
-+</complexType>
-+
-+<complexType name="X509IssuerSerialType"> 
-+  <sequence> 
-+    <element name="X509IssuerName" type="string"/> 
-+    <element name="X509SerialNumber" type="integer"/> 
-+  </sequence>
-+</complexType>
-+
-+<!-- End X509Data -->
-+
-+<!-- Begin PGPData -->
-+
-+<element name="PGPData" type="ds:PGPDataType"/> 
-+<complexType name="PGPDataType"> 
-+  <choice>
-+    <sequence>
-+      <element name="PGPKeyID" type="base64Binary"/> 
-+      <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/> 
-+      <any namespace="##other" processContents="lax" minOccurs="0"
-+       maxOccurs="unbounded"/>
-+    </sequence>
-+    <sequence>
-+      <element name="PGPKeyPacket" type="base64Binary"/> 
-+      <any namespace="##other" processContents="lax" minOccurs="0"
-+       maxOccurs="unbounded"/>
-+    </sequence>
-+  </choice>
-+</complexType>
-+
-+<!-- End PGPData -->
-+
-+<!-- Begin SPKIData -->
-+
-+<element name="SPKIData" type="ds:SPKIDataType"/> 
-+<complexType name="SPKIDataType">
-+  <sequence maxOccurs="unbounded">
-+    <element name="SPKISexp" type="base64Binary"/>
-+    <any namespace="##other" processContents="lax" minOccurs="0"/>
-+  </sequence>
-+</complexType> 
-+
-+<!-- End SPKIData -->
-+
-+<!-- End KeyInfo -->
-+
-+<!-- Start Object (Manifest, SignatureProperty) -->
-+
-+<element name="Object" type="ds:ObjectType"/> 
-+<complexType name="ObjectType" mixed="true">
-+  <sequence minOccurs="0" maxOccurs="unbounded">
-+    <any namespace="##any" processContents="lax"/>
-+  </sequence>
-+  <attribute name="Id" type="ID" use="optional"/> 
-+  <attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
-+  <attribute name="Encoding" type="anyURI" use="optional"/> 
-+</complexType>
-+
-+<element name="Manifest" type="ds:ManifestType"/> 
-+<complexType name="ManifestType">
-+  <sequence>
-+    <element ref="ds:Reference" maxOccurs="unbounded"/> 
-+  </sequence>
-+  <attribute name="Id" type="ID" use="optional"/> 
-+</complexType>
-+
-+<element name="SignatureProperties" type="ds:SignaturePropertiesType"/> 
-+<complexType name="SignaturePropertiesType">
-+  <sequence>
-+    <element ref="ds:SignatureProperty" maxOccurs="unbounded"/> 
-+  </sequence>
-+  <attribute name="Id" type="ID" use="optional"/> 
-+</complexType>
-+
-+   <element name="SignatureProperty" type="ds:SignaturePropertyType"/> 
-+   <complexType name="SignaturePropertyType" mixed="true">
-+     <choice maxOccurs="unbounded">
-+       <any namespace="##other" processContents="lax"/>
-+       <!-- (1,1) elements from (1,unbounded) namespaces -->
-+     </choice>
-+     <attribute name="Target" type="anyURI" use="required"/> 
-+     <attribute name="Id" type="ID" use="optional"/> 
-+   </complexType>
-+
-+<!-- End Object (Manifest, SignatureProperty) -->
-+
-+<!-- Start Algorithm Parameters -->
-+
-+<simpleType name="HMACOutputLengthType">
-+  <restriction base="integer"/>
-+</simpleType>
-+
-+<!-- Start KeyValue Element-types -->
-+
-+<element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
-+<complexType name="DSAKeyValueType">
-+  <sequence>
-+    <sequence minOccurs="0">
-+      <element name="P" type="ds:CryptoBinary"/>
-+      <element name="Q" type="ds:CryptoBinary"/>
-+    </sequence>
-+    <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
-+    <element name="Y" type="ds:CryptoBinary"/>
-+    <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
-+    <sequence minOccurs="0">
-+      <element name="Seed" type="ds:CryptoBinary"/>
-+      <element name="PgenCounter" type="ds:CryptoBinary"/>
-+    </sequence>
-+  </sequence>
-+</complexType>
-+
-+<element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
-+<complexType name="RSAKeyValueType">
-+  <sequence>
-+    <element name="Modulus" type="ds:CryptoBinary"/> 
-+    <element name="Exponent" type="ds:CryptoBinary"/> 
-+  </sequence>
-+</complexType> 
-+
-+<!-- End KeyValue Element-types -->
-+
-+<!-- End Signature -->
-+
-+</schema>
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ python-zeep/tests/wsdl_files/soap_import_2.wsdl	2016-12-06 18:24:05.000000000 +0100
-@@ -0,0 +1,42 @@
-+<?xml version="1.0"?>
-+<definitions 
-+    xmlns:tns="http://example.com/stockquote.wsdl" 
-+    xmlns:xsd1="http://example.com/stockquote.xsd" 
-+    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
-+    xmlns="http://schemas.xmlsoap.org/wsdl/"
-+    name="StockQuote" 
-+    targetNamespace="http://example.com/stockquote.wsdl">
-+  <types>
-+    <schema xmlns="http://www.w3.org/2001/XMLSchema" 
-+            targetNamespace="http://test.python-zeep.org/imports"
-+            xmlns:tns="http://test.python-zeep.org/imports">
-+      <import schemaLocation="test_import_2.xsd" namespace="http://example.com/stockquote.xsd"/>
-+    </schema>
-+    <schema xmlns="http://www.w3.org/2001/XMLSchema" 
-+            targetNamespace="http://test.python-zeep.org/something"
-+            xmlns:tns="http://test.python-zeep.org/something">
-+      <import namespace="http://schemas.xmlsoap.org/soap/encoding/" 
-+              schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/>
-+    </schema>
-+  </types>
-+  <message name="GetLastTradePriceInput">
-+    <part name="body" element="xsd1:TradePriceRequest"/>
-+  </message>
-+  <message name="GetLastTradePriceOutput">
-+    <part name="body" element="xsd1:TradePrice"/>
-+  </message>
-+  <message name="FaultMessageMsg1">
-+    <part name="fault1" element="xsd1:Fault1"/>
-+  </message>
-+  <message name="FaultMessageMsg2">
-+    <part name="fault2" element="xsd1:Fault2"/>
-+  </message>
-+  <portType name="StockQuotePortType">
-+    <operation name="GetLastTradePrice">
-+      <input message="tns:GetLastTradePriceInput"/>
-+      <output message="tns:GetLastTradePriceOutput"/>
-+      <fault message="tns:FaultMessageMsg1" name="fault1"/>
-+      <fault message="tns:FaultMessageMsg2" name="fault2"/>
-+    </operation>
-+  </portType>
-+</definitions>
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ python-zeep/tests/wsdl_files/soap_import_main.wsdl	2016-12-06 18:24:05.000000000 +0100
-@@ -0,0 +1,38 @@
-+<?xml version="1.0"?>
-+<definitions 
-+    xmlns:tns="http://example.com/stockquote.wsdl" 
-+    xmlns:xsd1="http://example.com/stockquote.xsd" 
-+    xmlns:sub="http://test.python-zeep.org/sub"
-+    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
-+    xmlns="http://schemas.xmlsoap.org/wsdl/"
-+    name="StockQuote" 
-+    targetNamespace="http://example.com/stockquote.wsdl">
-+  <import namespace="http://test.python-zeep.org/sub" location="soap_import_2.wsdl"/>
-+
-+  <types/>
-+  <binding name="StockQuoteBinding" type="tns:StockQuotePortType">
-+    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
-+    <operation name="GetLastTradePrice">
-+      <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
-+      <input>
-+        <soap:body use="literal"/>
-+      </input>
-+      <output>
-+        <soap:body use="literal"/>
-+      </output>
-+      <fault name="fault1">
-+        <soap:fault name="fault1" use="literal"/>
-+      </fault>
-+      <fault name="fault2">
-+        <soap:fault name="fault2" use="literal"/>
-+      </fault>
-+    </operation>
-+  </binding>
-+  <service name="StockQuoteService">
-+    <documentation>My first service</documentation>
-+    <port name="StockQuotePort" binding="tns:StockQuoteBinding">
-+      <soap:address location="http://example.com/stockquote"/>
-+    </port>
-+  </service>
-+</definitions>
-+
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index 3b984e6..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1 +0,0 @@
-01-add-missing-xsd-files.patch
commit d20635c0d4a826ef35c1821cab81024b52f09371
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Wed Dec 21 22:50:56 2016 +0100

    Merging upstream version 0.24.0.

diff --git a/CHANGES b/CHANGES
index 468f461..1b6c737 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,20 @@
+0.24.0 (2016-12-16)
+-------------------
+ - Don't fail the parsing of responses if an xsi:type references an non-existing
+   type. Instead log a message (#273)
+ - Fix serializing etree.Element instances in the helpers.serialize function
+   (#255)
+ - Fix infinite loop during parsing of xsd.Sequence where max_occurs is 
+   unbounded (#256)
+ - Make the xsd.Element name kwarg required
+ - Improve handling of the xsd:anyType element when passed instances of 
+   complexType's (#252)
+ - Silently ignore unsupported binding transports instead of an hard error 
+   (#277)
+ - Support microseconds for xsd.dateTime and xsd.Time (#280)
+ - Don't mutate passed values to the zeep operations (#280)
+
+
 0.23.0 (2016-11-24)
 -------------------
  - Add Client.set_default_soapheaders() to set soapheaders which are to be used
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 3244331..0000000
--- a/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-.PHONY: install clean test retest coverage docs
-
-install:
-	pip install -e .[docs,test]
-	pip install bumpversion twine wheel
-
-lint:
-	flake8 src/ tests/
-	isort --recursive --check-only --diff src tests
-
-clean:
-	find . -name '*.pyc' -delete
-
-test:
-	py.test -vvv
-
-retest:
-	py.test -vvv --lf
-
-coverage:
-	py.test --cov=zeep --cov-report=term-missing --cov-report=html
-
-docs:
-	$(MAKE) -C docs html
-
-release:
-	pip install twine wheel
-	rm -rf dist/*
-	python setup.py sdist bdist_wheel
-	twine upload -s dist/*
diff --git a/PKG-INFO b/PKG-INFO
index 0810ebd..fc65fe8 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: zeep
-Version: 0.23.0
+Version: 0.24.0
 Summary: A modern/fast Python SOAP client based on lxml / requests
 Home-page: http://docs.python-zeep.org
 Author: Michael van Tellingen
@@ -69,8 +69,10 @@ Description: ========================
         If you encounter bugs then please `let me know`_ .  A copy of the WSDL file if
         possible would be most helpful. 
         
-        I'm also able to offer commercial support.  Please contact me at
-        info at mvantellingen.nl for more information.
+        I'm also able to offer commercial support.  As in contracting work. Please
+        contact me at info at mvantellingen.nl for more information. If you just have a
+        random question and don't intent to actually pay me for my support then please
+        DO NOT email me at that e-mail address but just use stackoverflow or something..
         
         .. _let me know: https://github.com/mvantellingen/python-zeep/issues
         
diff --git a/README.rst b/README.rst
index 81d782f..e46a8b6 100644
--- a/README.rst
+++ b/README.rst
@@ -84,7 +84,9 @@ Support
 If you encounter bugs then please `let me know`_ .  A copy of the WSDL file if
 possible would be most helpful. 
 
-I'm also able to offer commercial support.  Please contact me at
-info at mvantellingen.nl for more information.
+I'm also able to offer commercial support.  As in contracting work. Please
+contact me at info at mvantellingen.nl for more information. If you just have a
+random question and don't intent to actually pay me for my support then please
+DO NOT email me at that e-mail address but just use stackoverflow or something..
 
 .. _let me know: https://github.com/mvantellingen/python-zeep/issues
diff --git a/docs/Makefile b/docs/Makefile
deleted file mode 100644
index 49c4227..0000000
--- a/docs/Makefile
+++ /dev/null
@@ -1,216 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS    =
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = _build
-
-# User-friendly check for sphinx-build
-ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
-$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
-endif
-
-# Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help
-help:
-	@echo "Please use \`make <target>' where <target> is one of"
-	@echo "  html       to make standalone HTML files"
-	@echo "  dirhtml    to make HTML files named index.html in directories"
-	@echo "  singlehtml to make a single large HTML file"
-	@echo "  pickle     to make pickle files"
-	@echo "  json       to make JSON files"
-	@echo "  htmlhelp   to make HTML files and a HTML help project"
-	@echo "  qthelp     to make HTML files and a qthelp project"
-	@echo "  applehelp  to make an Apple Help Book"
-	@echo "  devhelp    to make HTML files and a Devhelp project"
-	@echo "  epub       to make an epub"
-	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
-	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
-	@echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
-	@echo "  text       to make text files"
-	@echo "  man        to make manual pages"
-	@echo "  texinfo    to make Texinfo files"
-	@echo "  info       to make Texinfo files and run them through makeinfo"
-	@echo "  gettext    to make PO message catalogs"
-	@echo "  changes    to make an overview of all changed/added/deprecated items"
-	@echo "  xml        to make Docutils-native XML files"
-	@echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
-	@echo "  linkcheck  to check all external links for integrity"
-	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
-	@echo "  coverage   to run coverage check of the documentation (if enabled)"
-
-.PHONY: clean
-clean:
-	rm -rf $(BUILDDIR)/*
-
-.PHONY: html
-html:
-	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
-	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-.PHONY: dirhtml
-dirhtml:
-	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
-	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-.PHONY: singlehtml
-singlehtml:
-	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
-	@echo
-	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-.PHONY: pickle
-pickle:
-	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
-	@echo
-	@echo "Build finished; now you can process the pickle files."
-
-.PHONY: json
-json:
-	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
-	@echo
-	@echo "Build finished; now you can process the JSON files."
-
-.PHONY: htmlhelp
-htmlhelp:
-	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
-	@echo
-	@echo "Build finished; now you can run HTML Help Workshop with the" \
-	      ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-.PHONY: qthelp
-qthelp:
-	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
-	@echo
-	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
-	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
-	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Zeep.qhcp"
-	@echo "To view the help file:"
-	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Zeep.qhc"
-
-.PHONY: applehelp
-applehelp:
-	$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
-	@echo
-	@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
-	@echo "N.B. You won't be able to view it unless you put it in" \
-	      "~/Library/Documentation/Help or install it in your application" \
-	      "bundle."
-
-.PHONY: devhelp
-devhelp:
-	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
-	@echo
-	@echo "Build finished."
-	@echo "To view the help file:"
-	@echo "# mkdir -p $$HOME/.local/share/devhelp/Zeep"
-	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Zeep"
-	@echo "# devhelp"
-
-.PHONY: epub
-epub:
-	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
-	@echo
-	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-.PHONY: latex
-latex:
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-	@echo
-	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
-	@echo "Run \`make' in that directory to run these through (pdf)latex" \
-	      "(use \`make latexpdf' here to do that automatically)."
-
-.PHONY: latexpdf
-latexpdf:
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-	@echo "Running LaTeX files through pdflatex..."
-	$(MAKE) -C $(BUILDDIR)/latex all-pdf
-	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-.PHONY: latexpdfja
-latexpdfja:
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-	@echo "Running LaTeX files through platex and dvipdfmx..."
-	$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
-	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-.PHONY: text
-text:
-	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
-	@echo
-	@echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-.PHONY: man
-man:
-	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
-	@echo
-	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-.PHONY: texinfo
-texinfo:
-	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
-	@echo
-	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
-	@echo "Run \`make' in that directory to run these through makeinfo" \
-	      "(use \`make info' here to do that automatically)."
-
-.PHONY: info
-info:
-	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
-	@echo "Running Texinfo files through makeinfo..."
-	make -C $(BUILDDIR)/texinfo info
-	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-.PHONY: gettext
-gettext:
-	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
-	@echo
-	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-.PHONY: changes
-changes:
-	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
-	@echo
-	@echo "The overview file is in $(BUILDDIR)/changes."
-
-.PHONY: linkcheck
-linkcheck:
-	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
-	@echo
-	@echo "Link check complete; look for any errors in the above output " \
-	      "or in $(BUILDDIR)/linkcheck/output.txt."
-
-.PHONY: doctest
-doctest:
-	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
-	@echo "Testing of doctests in the sources finished, look at the " \
-	      "results in $(BUILDDIR)/doctest/output.txt."
-
-.PHONY: coverage
-coverage:
-	$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
-	@echo "Testing of coverage in the sources finished, look at the " \
-	      "results in $(BUILDDIR)/coverage/python.txt."
-
-.PHONY: xml
-xml:
-	$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
-	@echo
-	@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
-
-.PHONY: pseudoxml
-pseudoxml:
-	$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
-	@echo
-	@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/docs/_templates/sidebar-intro.html b/docs/_templates/sidebar-intro.html
deleted file mode 100644
index af3fb9e..0000000
--- a/docs/_templates/sidebar-intro.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-<a href="{{ pathto(master_doc) }}">
-    <img class="logo" src="{{ pathto('_static/zeep-logo.png', 1) }}">
-</a>
-
-<p>Zeep is a modern SOAP client for Python</p>
-<p>
-  <iframe src="http://ghbtns.com/github-btn.html?user=mvantellingen&repo=python-zeep&type=watch&count=true&size=large"
-    allowtransparency="true" frameborder="0" scrolling="0" width="200px" height="35px"></iframe>
-</p>
-
-<h3>Links</h3>
-<ul>
-  <li><a href="http://github.com/mvantellingen/python-zeep">Zeep @ GitHub</a></li>
-  <li><a href="http://pypi.python.org/pypi/zeep">Zeep @ PyPI</a></li>
-  <li><a href="http://github.com/mvantellingen/python-zeep/issues">Issue Tracker</a></li>
-</ul>
-
diff --git a/docs/conf.py b/docs/conf.py
deleted file mode 100644
index b233225..0000000
--- a/docs/conf.py
+++ /dev/null
@@ -1,299 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Zeep documentation build configuration file, created by
-# sphinx-quickstart on Fri Mar  4 16:51:06 2016.
-#
-# This file is execfile()d with the current directory set to its
-# containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys
-import os
-import pkg_resources
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
-
-# -- General configuration ------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = ['sphinx.ext.autodoc']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'Zeep'
-copyright = u'2016, <a href="https://www.mvantellingen.nl/">Michael van Tellingen</a>'
-author = u'Michael van Tellingen'
-
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-version = '0.23.0'
-release = version
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
-
-# The reST default role (used for this markup: `text`) to use for all
-# documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-# If true, keep warnings as "system message" paragraphs in the built documents.
-#keep_warnings = False
-
-# If true, `todo` and `todoList` produce output, else they produce nothing.
-todo_include_todos = False
-
-
-autodoc_default_flags = [':members:']
-
-
-# -- Options for HTML output ----------------------------------------------
-
-# The theme to use for HTML and HTML Help pages.  See the documentation for
-# a list of builtin themes.
-html_theme = 'alabaster'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further.  For a list of options available for each theme, see the
-# documentation.
-html_theme_options = {
-    'github_user': 'mvantellingen',
-    'github_banner': True,
-    'github_repo': 'python-zeep',
-    'travis_button': True,
-    'codecov_button': True,
-    'analytics_id':  'UA-75907833-1',
-}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (relative to this directory) to use as a favicon of
-# the docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# Add any extra paths that contain custom files (such as robots.txt or
-# .htaccess) here, relative to this directory. These files are copied
-# directly to the root of the documentation.
-#html_extra_path = []
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-html_sidebars = {
-    '*': [
-        'sidebar-intro.html', 'globaltoc.html', 'sourcelink.html',
-        'searchbox.html'
-    ]
-}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.  The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Language to be used for generating the HTML full-text search index.
-# Sphinx supports the following languages:
-#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
-#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
-#html_search_language = 'en'
-
-# A dictionary with options for the search language support, empty by default.
-# Now only 'ja' uses this config value
-#html_search_options = {'type': 'default'}
-
-# The name of a javascript file (relative to the configuration directory) that
-# implements a search results scorer. If empty, the default will be used.
-#html_search_scorer = 'scorer.js'
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'Zeepdoc'
-
-# -- Options for LaTeX output ---------------------------------------------
-
-latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-
-# Latex figure (float) alignment
-#'figure_align': 'htbp',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-#  author, documentclass [howto, manual, or own class]).
-latex_documents = [
-    (master_doc, 'Zeep.tex', u'Zeep Documentation',
-     u'Michael van Tellingen', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output ---------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
-    (master_doc, 'zeep', u'Zeep Documentation',
-     [author], 1)
-]
-
-# If true, show URL addresses after external links.
-#man_show_urls = False
-
-
-# -- Options for Texinfo output -------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-#  dir menu entry, description, category)
-texinfo_documents = [
-    (master_doc, 'Zeep', u'Zeep Documentation',
-     author, 'Zeep', 'One line description of project.',
-     'Miscellaneous'),
-]
-
-# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
-
-# If false, no module index is generated.
-#texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
-
-# If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
diff --git a/docs/index.rst b/docs/index.rst
deleted file mode 100644
index 2aeb016..0000000
--- a/docs/index.rst
+++ /dev/null
@@ -1,131 +0,0 @@
-========================
-Zeep: Python SOAP client 
-========================
-
-A fast and modern Python SOAP client
-
-Highlights:
- * Modern codebase compatible with Python 2.7, 3.3, 3.4, 3.5 and PyPy
- * Build on top of lxml and requests
- * Supports recursive WSDL and XSD documents.
- * Supports the xsd:choice and xsd:any elements.
- * Uses the defusedxml module for handling potential XML security issues
- * Support for WSSE (UsernameToken only for now)
- * Experimental support for HTTP bindings
- * Experimental support for WS-Addressing headers
- * Experimental support for asyncio via aiohttp (Python 3.5+)
-
-Features still in development include:
- * WSSE x.509 support (BinarySecurityToken)
- * WS Policy support
-
-
-A simple example:
-
-.. code-block:: python
-
-    from zeep import Client
-
-    client = Client('http://www.webservicex.net/ConvertSpeed.asmx?WSDL')
-    result = client.service.ConvertSpeed(
-        100, 'kilometersPerhour', 'milesPerhour')
-
-    assert result == 62.137
-
-
-Quick Introduction
-==================
-
-Zeep inspects the wsdl document and generates the corresponding bindings.  This
-provides an easy to use programmatic interface to a soap server.
-
-The emphasis is on Soap 1.1 and Soap 1.2, however Zeep also offers experimental
-support for HTTP Get and Post bindings.
-
-Parsing the XML documents is done by using the lxml library. This is the most
-performant and compliant Python XML library currently available. This results
-in major speed benefits when retrieving large soap responses.
-
-The SOAP specifications are unfortunately really vague and leave a lot of
-things open for interpretation.  Due to this there are a lot of WSDL documents
-available which are invalid or SOAP servers which contain bugs. Zeep tries to
-be as compatible as possible but there might be cases where you run into 
-problems. Don't hesitate to submit an issue in this case (please see 
-:ref:`reporting_bugs`).
-
-
-Getting started
-===============
-
-You can install the latest version of zeep using pip::
-
-    pip install zeep
-
-The first thing you generally want to do is inspect the wsdl file you need to
-implement. This can be done with::
-
-    python -mzeep <wsdl>
-
-
-See ``python -mzeep --help`` for more information about this command.
-
-
-.. note:: Since this module hasn't reached 1.0.0 yet their might be minor
-          releases which introduce backwards compatible changes. While I try 
-          to keep this to a minimum it can still happen. So as always pin the 
-          version of zeep you used (e.g. ``zeep==0.14.0``').
-
-
-
-A simple use-case
------------------
-
-To give you an idea how zeep works a basic example.
-
-.. code-block:: python
-
-    import zeep
-
-    wsdl = 'http://www.soapclient.com/xml/soapresponder.wsdl'
-    client = zeep.Client(wsdl=wsdl)
-    print(client.service.Method1('Zeep', 'is cool'))
-
-The WSDL used above only defines one simple function (``Method1``) which is 
-made available by zeep via ``client.service.Method1``. It takes two arguments
-and returns a string. To get an overview of the services available on the 
-endpoint you can run the following command in your terminal.
-
-.. code-block:: bash
-
-    python -mzeep http://www.soapclient.com/xml/soapresponder.wsdl
-
-
-More information
-================
-
-.. toctree::
-   :maxdepth: 2
-   :name: mastertoc
-
-   in_depth
-   datastructures
-   transport
-   wsa
-   wsse
-   plugins
-   helpers
-   reporting_bugs
-   changes
-
-
-Support
-=======
-
-If you encounter bugs then please `let me know`_ . Please see :doc:`reporting_bugs`
-for information how to best report them.
-
-I'm also able to offer commercial support.  Please contact me at
-info at mvantellingen.nl for more information.
-
-
-.. _let me know: https://github.com/mvantellingen/python-zeep/issues
diff --git a/docs/make.bat b/docs/make.bat
deleted file mode 100644
index bb121e7..0000000
--- a/docs/make.bat
+++ /dev/null
@@ -1,263 +0,0 @@
- at ECHO OFF
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
-	set SPHINXBUILD=sphinx-build
-)
-set BUILDDIR=_build
-set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
-set I18NSPHINXOPTS=%SPHINXOPTS% .
-if NOT "%PAPER%" == "" (
-	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
-	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
-)
-
-if "%1" == "" goto help
-
-if "%1" == "help" (
-	:help
-	echo.Please use `make ^<target^>` where ^<target^> is one of
-	echo.  html       to make standalone HTML files
-	echo.  dirhtml    to make HTML files named index.html in directories
-	echo.  singlehtml to make a single large HTML file
-	echo.  pickle     to make pickle files
-	echo.  json       to make JSON files
-	echo.  htmlhelp   to make HTML files and a HTML help project
-	echo.  qthelp     to make HTML files and a qthelp project
-	echo.  devhelp    to make HTML files and a Devhelp project
-	echo.  epub       to make an epub
-	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
-	echo.  text       to make text files
-	echo.  man        to make manual pages
-	echo.  texinfo    to make Texinfo files
-	echo.  gettext    to make PO message catalogs
-	echo.  changes    to make an overview over all changed/added/deprecated items
-	echo.  xml        to make Docutils-native XML files
-	echo.  pseudoxml  to make pseudoxml-XML files for display purposes
-	echo.  linkcheck  to check all external links for integrity
-	echo.  doctest    to run all doctests embedded in the documentation if enabled
-	echo.  coverage   to run coverage check of the documentation if enabled
-	goto end
-)
-
-if "%1" == "clean" (
-	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
-	del /q /s %BUILDDIR%\*
-	goto end
-)
-
-
-REM Check if sphinx-build is available and fallback to Python version if any
-%SPHINXBUILD% 1>NUL 2>NUL
-if errorlevel 9009 goto sphinx_python
-goto sphinx_ok
-
-:sphinx_python
-
-set SPHINXBUILD=python -m sphinx.__init__
-%SPHINXBUILD% 2> nul
-if errorlevel 9009 (
-	echo.
-	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
-	echo.installed, then set the SPHINXBUILD environment variable to point
-	echo.to the full path of the 'sphinx-build' executable. Alternatively you
-	echo.may add the Sphinx directory to PATH.
-	echo.
-	echo.If you don't have Sphinx installed, grab it from
-	echo.http://sphinx-doc.org/
-	exit /b 1
-)
-
-:sphinx_ok
-
-
-if "%1" == "html" (
-	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
-	goto end
-)
-
-if "%1" == "dirhtml" (
-	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
-	goto end
-)
-
-if "%1" == "singlehtml" (
-	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
-	goto end
-)
-
-if "%1" == "pickle" (
-	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; now you can process the pickle files.
-	goto end
-)
-
-if "%1" == "json" (
-	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; now you can process the JSON files.
-	goto end
-)
-
-if "%1" == "htmlhelp" (
-	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; now you can run HTML Help Workshop with the ^
-.hhp project file in %BUILDDIR%/htmlhelp.
-	goto end
-)
-
-if "%1" == "qthelp" (
-	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; now you can run "qcollectiongenerator" with the ^
-.qhcp project file in %BUILDDIR%/qthelp, like this:
-	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Zeep.qhcp
-	echo.To view the help file:
-	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Zeep.ghc
-	goto end
-)
-
-if "%1" == "devhelp" (
-	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished.
-	goto end
-)
-
-if "%1" == "epub" (
-	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The epub file is in %BUILDDIR%/epub.
-	goto end
-)
-
-if "%1" == "latex" (
-	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
-	goto end
-)
-
-if "%1" == "latexpdf" (
-	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
-	cd %BUILDDIR%/latex
-	make all-pdf
-	cd %~dp0
-	echo.
-	echo.Build finished; the PDF files are in %BUILDDIR%/latex.
-	goto end
-)
-
-if "%1" == "latexpdfja" (
-	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
-	cd %BUILDDIR%/latex
-	make all-pdf-ja
-	cd %~dp0
-	echo.
-	echo.Build finished; the PDF files are in %BUILDDIR%/latex.
-	goto end
-)
-
-if "%1" == "text" (
-	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The text files are in %BUILDDIR%/text.
-	goto end
-)
-
-if "%1" == "man" (
-	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The manual pages are in %BUILDDIR%/man.
-	goto end
-)
-
-if "%1" == "texinfo" (
-	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
-	goto end
-)
-
-if "%1" == "gettext" (
-	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
-	goto end
-)
-
-if "%1" == "changes" (
-	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.The overview file is in %BUILDDIR%/changes.
-	goto end
-)
-
-if "%1" == "linkcheck" (
-	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Link check complete; look for any errors in the above output ^
-or in %BUILDDIR%/linkcheck/output.txt.
-	goto end
-)
-
-if "%1" == "doctest" (
-	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Testing of doctests in the sources finished, look at the ^
-results in %BUILDDIR%/doctest/output.txt.
-	goto end
-)
-
-if "%1" == "coverage" (
-	%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Testing of coverage in the sources finished, look at the ^
-results in %BUILDDIR%/coverage/python.txt.
-	goto end
-)
-
-if "%1" == "xml" (
-	%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The XML files are in %BUILDDIR%/xml.
-	goto end
-)
-
-if "%1" == "pseudoxml" (
-	%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
-	if errorlevel 1 exit /b 1
-	echo.
-	echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
-	goto end
-)
-
-:end
diff --git a/examples/code39.py b/examples/code39.py
deleted file mode 100644
index eda664f..0000000
--- a/examples/code39.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import print_function
-import zeep
-
-
-client = zeep.Client(
-    wsdl='http://www.webservicex.net/barcode.asmx?WSDL')
-response = client.service.Code39('1234', 20, ShowCodeString=True, Title='ZEEP')
-print(repr(response))
diff --git a/examples/echo_services.py b/examples/echo_services.py
deleted file mode 100644
index 5270f95..0000000
--- a/examples/echo_services.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from zeep.client import Client
-
-# RPC style soap service
-client = Client('http://www.soapclient.com/xml/soapresponder.wsdl')
-print(client.service.Method1('zeep', 'soap'))
diff --git a/examples/eu_vat_service.py b/examples/eu_vat_service.py
deleted file mode 100644
index e5ba15e..0000000
--- a/examples/eu_vat_service.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import print_function
-import zeep
-
-
-client = zeep.Client(
-    wsdl='http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl')
-print(client.service.checkVat('NL', '170944128B01'))
diff --git a/examples/km_to_miles.py b/examples/km_to_miles.py
deleted file mode 100644
index d8821df..0000000
--- a/examples/km_to_miles.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import print_function
-import zeep
-
-
-client = zeep.Client(
-    wsdl='http://www.webservicex.net/ConvertSpeed.asmx?WSDL')
-
-client.wsdl.dump()
-
-print (client.service.ConvertSpeed(100, 'kilometersPerhour', 'milesPerhour'))
-
-http_get = client.bind('ConvertSpeeds', 'ConvertSpeedsHttpGet')
-http_post = client.bind('ConvertSpeeds', 'ConvertSpeedsHttpPost')
-
-print(http_get.ConvertSpeed(100, 'kilometersPerhour', 'milesPerhour'))
-print(http_post.ConvertSpeed(100, 'kilometersPerhour', 'milesPerhour'))
diff --git a/setup.py b/setup.py
index 8ba07bf..ea27113 100755
--- a/setup.py
+++ b/setup.py
@@ -37,7 +37,7 @@ with open('README.rst') as fh:
 
 setup(
     name='zeep',
-    version='0.23.0',
+    version='0.24.0',
     description='A modern/fast Python SOAP client based on lxml / requests',
     long_description=long_description,
     author="Michael van Tellingen",
diff --git a/src/zeep/__init__.py b/src/zeep/__init__.py
index 606d054..22d0183 100644
--- a/src/zeep/__init__.py
+++ b/src/zeep/__init__.py
@@ -2,4 +2,4 @@ from zeep.client import Client  # noqa
 from zeep.transports import Transport  # noqa
 from zeep.plugins import Plugin  # noqa
 
-__version__ = '0.23.0'
+__version__ = '0.24.0'
diff --git a/src/zeep/helpers.py b/src/zeep/helpers.py
index 27df819..eec2e69 100644
--- a/src/zeep/helpers.py
+++ b/src/zeep/helpers.py
@@ -1,5 +1,7 @@
 from collections import OrderedDict
 
+from lxml import etree
+
 from zeep.xsd.valueobjects import CompoundValue
 
 
@@ -8,6 +10,9 @@ def serialize_object(obj):
     if obj is None:
         return obj
 
+    if isinstance(obj, etree._Element):
+        return obj
+
     if isinstance(obj, list):
         return [serialize_object(sub) for sub in obj]
 
diff --git a/src/zeep/wsdl/bindings/soap.py b/src/zeep/wsdl/bindings/soap.py
index b700434..2f86319 100644
--- a/src/zeep/wsdl/bindings/soap.py
+++ b/src/zeep/wsdl/bindings/soap.py
@@ -193,7 +193,9 @@ class SoapBinding(Binding):
         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")
+            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)
diff --git a/src/zeep/wsdl/messages/soap.py b/src/zeep/wsdl/messages/soap.py
index b1b64b6..3875ecf 100644
--- a/src/zeep/wsdl/messages/soap.py
+++ b/src/zeep/wsdl/messages/soap.py
@@ -288,6 +288,8 @@ class SoapMessage(ConcreteMessage):
             for header_value in headers_value:
                 if hasattr(header_value, '_xsd_elm'):
                     header_value._xsd_elm.render(header, header_value)
+                elif hasattr(header_value, '_xsd_type'):
+                    header_value._xsd_type.render(header, header_value)
                 elif isinstance(header_value, etree._Element):
                     header.append(header_value)
                 else:
@@ -298,7 +300,7 @@ class SoapMessage(ConcreteMessage):
                     "_soapheaders only accepts a dictionary if the wsdl "
                     "defines the headers.")
             headers_value = self.header(**headers_value)
-            self.header.render(header, headers_value)
+            self.header.type.render(header, headers_value)
         else:
             raise ValueError("Invalid value given to _soapheaders")
 
@@ -315,9 +317,11 @@ class SoapMessage(ConcreteMessage):
         return {}
 
     def _resolve_header(self, info, definitions, parts):
+        name = etree.QName(self.nsmap['soap-env'], 'Header')
+
         sequence = xsd.Sequence()
         if not info:
-            return xsd.Element(None, xsd.ComplexType(sequence))
+            return xsd.Element(name, xsd.ComplexType(sequence))
 
         for item in info:
             message_name = item['message'].text
@@ -334,7 +338,7 @@ class SoapMessage(ConcreteMessage):
             else:
                 element = xsd.Element(part_name, part.type)
             sequence.append(element)
-        return xsd.Element(None, xsd.ComplexType(sequence))
+        return xsd.Element(name, xsd.ComplexType(sequence))
 
 
 class DocumentMessage(SoapMessage):
@@ -360,8 +364,10 @@ class DocumentMessage(SoapMessage):
         return {'body': result}
 
     def _resolve_body(self, info, definitions, parts):
+        name = etree.QName(self.nsmap['soap-env'], 'Body')
+
         if not info or not parts:
-            return xsd.Element(None, xsd.ComplexType([]))
+            return xsd.Element(name, xsd.ComplexType([]))
 
         # If the part name is omitted then all parts are available under
         # the soap:body tag. Otherwise only the part with the given name.
@@ -377,8 +383,7 @@ class DocumentMessage(SoapMessage):
 
         if len(sub_elements) > 1:
             self._is_body_wrapped = True
-            return xsd.Element(
-                None, xsd.ComplexType(xsd.All(sub_elements)))
+            return xsd.Element(name, xsd.ComplexType(xsd.All(sub_elements)))
         else:
             self._is_body_wrapped = False
             return sub_elements[0]
@@ -404,8 +409,9 @@ class RpcMessage(SoapMessage):
         name and its namespace is the value of the namespace attribute.
 
         """
+        name = etree.QName(self.nsmap['soap-env'], 'Body')
         if not info:
-            return xsd.Element(None, xsd.ComplexType([]))
+            return xsd.Element(name, xsd.ComplexType([]))
 
         namespace = info['namespace']
         if self.type == 'input':
diff --git a/src/zeep/wsdl/wsdl.py b/src/zeep/wsdl/wsdl.py
index 3eb247c..ce14b66 100644
--- a/src/zeep/wsdl/wsdl.py
+++ b/src/zeep/wsdl/wsdl.py
@@ -358,7 +358,12 @@ class Definition(object):
             binding = None
             for binding_class in binding_classes:
                 if binding_class.match(binding_node):
-                    binding = binding_class.parse(self, binding_node)
+
+                    try:
+                        binding = binding_class.parse(self, binding_node)
+                    except NotImplementedError as exc:
+                        logger.debug("Ignoring binding: %s", exc)
+                        continue
 
                     logger.debug("Adding binding: %s", binding.name.text)
                     result[binding.name.text] = binding
diff --git a/src/zeep/xsd/builtins.py b/src/zeep/xsd/builtins.py
index 5219ae5..a4b64f3 100644
--- a/src/zeep/xsd/builtins.py
+++ b/src/zeep/xsd/builtins.py
@@ -179,6 +179,8 @@ class DateTime(_BuiltinType):
 
     @check_no_collection
     def xmlvalue(self, value):
+        if value.microsecond:
+            return isodate.isostrf.strftime(value, '%Y-%m-%dT%H:%M:%S.%f%Z')
         return isodate.isostrf.strftime(value, '%Y-%m-%dT%H:%M:%S%Z')
 
     def pythonvalue(self, value):
@@ -191,6 +193,8 @@ class Time(_BuiltinType):
 
     @check_no_collection
     def xmlvalue(self, value):
+        if value.microsecond:
+            return isodate.isostrf.strftime(value, '%H:%M:%S.%f%Z')
         return isodate.isostrf.strftime(value, '%H:%M:%S%Z')
 
     def pythonvalue(self, value):
@@ -512,6 +516,9 @@ class AnyType(_BuiltinType):
         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)
 
@@ -525,7 +532,12 @@ class AnyType(_BuiltinType):
             return None
 
         if xsi_type and schema:
-            xsd_type = schema.get_type(xsi_type)
+            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.
diff --git a/src/zeep/xsd/elements.py b/src/zeep/xsd/elements.py
index e7e3d87..8a62188 100644
--- a/src/zeep/xsd/elements.py
+++ b/src/zeep/xsd/elements.py
@@ -28,13 +28,14 @@ class Base(object):
     def is_optional(self):
         return self.min_occurs == 0
 
-    def parse_args(self, args):
+    def parse_args(self, args, index=0):
         result = {}
         if not args:
-            return result, args
+            return result, args, index
 
-        value = args.pop(0)
-        return {self.attr_name: value}, args
+        value = args[index]
+        index += 1
+        return {self.attr_name: value}, args, index
 
     def parse_kwargs(self, kwargs, name, available_kwargs):
         raise NotImplementedError()
@@ -146,7 +147,7 @@ class Any(Base):
             self._render_value_item(parent, value)
 
     def _render_value_item(self, parent, value):
-        if not value:
+        if value is None:  # can be an lxml element
             return
 
         # Check if we received a proper value object. If we receive the wrong
@@ -202,7 +203,9 @@ class Any(Base):
 class Element(Base):
     def __init__(self, name, type_=None, min_occurs=1, max_occurs=1,
                  nillable=False, default=None, is_global=False, attr_name=None):
-        if name and not isinstance(name, etree.QName):
+        if name is None:
+            raise ValueError("name cannot be None", self.__class__)
+        if not isinstance(name, etree.QName):
             name = etree.QName(name)
 
         self.name = name.localname if name else None
@@ -264,10 +267,10 @@ class Element(Base):
         """
         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)
-        else:
-            xsd_type = self.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)
 
@@ -343,9 +346,6 @@ class Element(Base):
                 elm.set(xsi_ns('nil'), 'true')
             return
 
-        if self.name is None:
-            return self.type.render(parent, value)
-
         node = etree.SubElement(parent, self.qname)
         xsd_type = getattr(value, '_xsd_type', self.type)
 
diff --git a/src/zeep/xsd/indicators.py b/src/zeep/xsd/indicators.py
index 2ba117c..ccfe423 100644
--- a/src/zeep/xsd/indicators.py
+++ b/src/zeep/xsd/indicators.py
@@ -97,15 +97,15 @@ class OrderIndicator(Indicator, list):
                 num += element.accept(values)
         return num
 
-    def parse_args(self, args):
+    def parse_args(self, args, index=0):
         result = {}
         for name, element in self.elements:
-            if not args:
+            if index >= len(args):
                 break
-            arg = args.pop(0)
-            result[name] = arg
+            result[name] = args[index]
+            index += 1
 
-        return result, args
+        return result, args, index
 
     def parse_kwargs(self, kwargs, name, available_kwargs):
         """Apply the given kwarg to the element.
@@ -164,12 +164,7 @@ class OrderIndicator(Indicator, list):
         return self
 
     def render(self, parent, value):
-        """Create subelements in the given parent object.
-
-        To make sure we render values only once the value items are copied
-        and the rendered attribute is removed from it once it is rendered.
-
-        """
+        """Create subelements in the given parent object."""
         if not isinstance(value, list):
             values = [value]
         else:
@@ -180,7 +175,6 @@ class OrderIndicator(Indicator, list):
                 if name:
                     if name in value:
                         element_value = value[name]
-                        del value[name]
                     else:
                         element_value = None
                 else:
@@ -256,8 +250,9 @@ class Choice(OrderIndicator):
         result = []
 
         for i in max_occurs_iter(self.max_occurs):
-            if len(xmlelements) < 1:
+            if not xmlelements:
                 break
+
             for node in list(xmlelements):
 
                 # Choose out of multiple
@@ -409,7 +404,7 @@ class Choice(OrderIndicator):
             else:
                 num = element.accept(values)
                 nums.add(num)
-        return max(nums)
+        return max(nums) if nums else 0
 
     def _find_element_to_render(self, value):
         """Return a tuple (element, value) for the best matching choice"""
@@ -460,6 +455,9 @@ class Sequence(OrderIndicator):
     def parse_xmlelements(self, xmlelements, schema, name=None, context=None):
         result = []
         for item in max_occurs_iter(self.max_occurs):
+            if not xmlelements:
+                break
+
             item_result = OrderedDict()
             for elm_name, element in self.elements:
                 item_subresult = element.parse_xmlelements(
@@ -516,8 +514,8 @@ class Group(Indicator):
             return [('_value_1', self.child)]
         return self.child.elements
 
-    def parse_args(self, args):
-        return self.child.parse_args(args)
+    def parse_args(self, args, index=0):
+        return self.child.parse_args(args, index)
 
     def parse_kwargs(self, kwargs, name, available_kwargs):
         if self.accepts_multiple:
diff --git a/src/zeep/xsd/schema.py b/src/zeep/xsd/schema.py
index 000ac95..3f9da9f 100644
--- a/src/zeep/xsd/schema.py
+++ b/src/zeep/xsd/schema.py
@@ -106,7 +106,7 @@ class Schema(object):
                 "No schema available for the namespace %r."
             ) % (qname.text, qname.namespace))
 
-    def get_type(self, qname):
+    def get_type(self, qname, fail_silently=False):
         """Return a global xsd.Type object with the given qname"""
         qname = self._create_qname(qname)
 
@@ -121,10 +121,15 @@ class Schema(object):
             schema = self._get_schema_document(qname.namespace)
             return schema.get_type(qname)
         except exceptions.NamespaceError:
-            raise exceptions.NamespaceError((
+            message = (
                 "Unable to resolve type %s. " +
                 "No schema available for the namespace %r."
-            ) % (qname.text, qname.namespace))
+            ) % (qname.text, qname.namespace)
+
+            if fail_silently:
+                logger.info(message)
+            else:
+                raise exceptions.NamespaceError(message)
 
     def get_group(self, qname):
         """Return a global xsd.Group object with the given qname"""
diff --git a/src/zeep/xsd/types.py b/src/zeep/xsd/types.py
index 7ce7522..87901b1 100644
--- a/src/zeep/xsd/types.py
+++ b/src/zeep/xsd/types.py
@@ -355,8 +355,11 @@ class ComplexType(Type):
             else:
                 element.render(parent, element_value)
 
-        if xsd_type and xsd_type._xsd_name:
-            parent.set(xsi_ns('type'), xsd_type._xsd_name)
+        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)
 
     def parse_kwargs(self, kwargs, name, available_kwargs):
         value = None
diff --git a/src/zeep/xsd/valueobjects.py b/src/zeep/xsd/valueobjects.py
index 2a508df..8cd5f18 100644
--- a/src/zeep/xsd/valueobjects.py
+++ b/src/zeep/xsd/valueobjects.py
@@ -55,6 +55,13 @@ class CompoundValue(object):
     def __contains__(self, key):
         return self.__values__.__contains__(key)
 
+    def __eq__(self, other):
+        if self.__class__ != other.__class__:
+            return False
+
+        other_values = {key: other[key] for key in other}
+        return other_values == self.__values__
+
     def __len__(self):
         return self.__values__.__len__()
 
@@ -118,21 +125,24 @@ def _process_signature(xsd_type, args, kwargs):
     if args:
         args = list(args)
         num_args = len(args)
+        index = 0
 
         for element_name, element in xsd_type.elements_nested:
-            values, args = element.parse_args(args)
+            values, args, index = element.parse_args(args, index)
             if not values:
                 break
             result.update(values)
 
-    if args:
         for attribute_name, attribute in xsd_type.attributes:
-            result[attribute_name] = args.pop(0)
+            if num_args <= index:
+                break
+            result[attribute_name] = args[index]
+            index += 1
 
-    if args:
-        raise TypeError(
-            "__init__() takes at most %s positional arguments (%s given)" % (
-                len(result), num_args))
+        if num_args > index:
+            raise TypeError(
+                "__init__() takes at most %s positional arguments (%s given)" % (
+                    len(result), num_args))
 
     # Process the named arguments (sequence/group/all/choice). The
     # available_kwargs set is modified in-place.
diff --git a/tests/integration/test_http_post.py b/tests/integration/test_http_post.py
new file mode 100644
index 0000000..dfcb992
--- /dev/null
+++ b/tests/integration/test_http_post.py
@@ -0,0 +1,34 @@
+import os
+
+import pytest
+import requests_mock
+
+import zeep
+
+WSDL = os.path.join(os.path.dirname(__file__), 'test_http_post.wsdl')
+
+
+ at pytest.mark.requests
+def test_get_urlreplacement():
+    client = zeep.Client(WSDL)
+
+    with requests_mock.mock() as m:
+        m.get('http://example.com/companyinfo/o1/EUR/', text='<root>Hoi</root>')
+        result = client.service.o1('EUR')
+        assert result == 'Hoi'
+
+        history = m.request_history[0]
+        assert history._request.path_url == '/companyinfo/o1/EUR/'
+
+
+ at pytest.mark.requests
+def test_post_mime_content():
+    client = zeep.Client(WSDL, service_name='CompanyInfoService', port_name='Port3')
+
+    with requests_mock.mock() as m:
+        m.post('http://example.com/companyinfo/o1', text='<root>Hoi</root>')
+        result = client.service.o1('EUR')
+        assert result == 'Hoi'
+
+        history = m.request_history[0]
+        assert history._request.path_url == '/companyinfo/o1'
diff --git a/tests/integration/test_http_post.wsdl b/tests/integration/test_http_post.wsdl
new file mode 100644
index 0000000..5a33e1c
--- /dev/null
+++ b/tests/integration/test_http_post.wsdl
@@ -0,0 +1,74 @@
+<?xml version="1.0"?>
+<definitions 
+  xmlns="http://schemas.xmlsoap.org/wsdl/"
+  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
+  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" 
+  xmlns:tns="http://test.python-zeep.org/tns/"
+  targetNamespace="http://test.python-zeep.org/tns/">
+  <types>
+    <xsd:schema></xsd:schema>
+  </types>
+  <message name="m1">
+    <part name="tickerSymbol" type="xsd:string"/>
+  </message>
+  <message name="m2">
+    <part name="image" type="xsd:hexBinary"/>
+  </message>
+  <portType name="pt1">
+    <operation name="o1">
+      <input message="tns:m1"/>
+      <output message="tns:m2"/>
+    </operation>
+  </portType>
+  <binding name="b1" type="pt1">
+    <http:binding verb="GET"/>
+    <operation name="o1">
+      <http:operation location="/o1/(tickerSymbol)/"/>
+      <input>
+        <http:urlReplacement/>
+      </input>
+      <output>
+        <mime:content type="image/gif"/>
+        <mime:content type="image/jpeg"/>
+      </output>
+    </operation>
+  </binding>
+  <binding name="b2" type="pt1">
+    <http:binding verb="GET"/>
+    <operation name="o1">
+      <http:operation location="/o1"/>
+      <input>
+        <http:urlEncoded/>
+      </input>
+      <output>
+        <mime:content type="image/gif"/>
+        <mime:content type="image/jpeg"/>
+      </output>
+    </operation>
+  </binding>
+  <binding name="b3" type="pt1">
+    <http:binding verb="POST"/>
+    <operation name="o1">
+      <http:operation location="/o1"/>
+      <input>
+        <mime:content type="application/x-www-form-urlencoded"/>
+      </input>
+      <output>
+        <mime:content type="image/gif"/>
+        <mime:content type="image/jpeg"/>
+      </output>
+    </operation>
+  </binding>
+  <service name="CompanyInfoService">
+    <port name="Port1" binding="tns:b1">
+      <http:address location="http://example.com/companyinfo"/>
+    </port>
+    <port name="Port2" binding="tns:b2">
+      <http:address location="http://example.com/companyinfo"/>
+    </port>
+    <port name="Port3" binding="tns:b3">
+      <http:address location="http://example.com/companyinfo"/>
+    </port>
+  </service>
+</definitions>
diff --git a/tests/test_client.py b/tests/test_client.py
index 122abc3..19dfb5c 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -16,6 +16,12 @@ def test_bind():
     assert service
 
 
+def test_unknown_transport():
+    client_obj = client.Client('tests/wsdl_files/soap_transport_err.wsdl')
+    service = client_obj.bind()
+    assert service
+
+
 def test_bind_service():
     client_obj = client.Client('tests/wsdl_files/soap.wsdl')
     service = client_obj.bind('StockQuoteService')
@@ -174,13 +180,13 @@ def test_set_context_options_timeout():
 
 @pytest.mark.requests
 def test_default_soap_headers():
-    header = xsd.Element(None, xsd.ComplexType(
+    header = xsd.ComplexType(
         xsd.Sequence([
             xsd.Element('{http://tests.python-zeep.org}name', xsd.String()),
             xsd.Element('{http://tests.python-zeep.org}password', xsd.String()),
         ])
-    ))
-    header_value = header(name='ik', password='geheim')
+    )
+    header_value = header(name='ik', password='foo')
 
     client_obj = client.Client('tests/wsdl_files/soap.wsdl')
     client_obj.set_default_soapheaders([header_value])
@@ -211,20 +217,20 @@ def test_default_soap_headers():
 
 @pytest.mark.requests
 def test_default_soap_headers_extra():
-    header = xsd.Element(None, xsd.ComplexType(
+    header = xsd.ComplexType(
         xsd.Sequence([
             xsd.Element('{http://tests.python-zeep.org}name', xsd.String()),
             xsd.Element('{http://tests.python-zeep.org}password', xsd.String()),
         ])
-    ))
+    )
     header_value = header(name='ik', password='geheim')
 
-    extra_header = xsd.Element(None, xsd.ComplexType(
+    extra_header = xsd.ComplexType(
         xsd.Sequence([
             xsd.Element('{http://tests.python-zeep.org}name', xsd.String()),
             xsd.Element('{http://tests.python-zeep.org}password', xsd.String()),
         ])
-    ))
+    )
     extra_header_value = extra_header(name='ik', password='geheim')
 
     client_obj = client.Client('tests/wsdl_files/soap.wsdl')
diff --git a/tests/test_client_factory.py b/tests/test_client_factory.py
new file mode 100644
index 0000000..92d5b1a
--- /dev/null
+++ b/tests/test_client_factory.py
@@ -0,0 +1,35 @@
+import pytest
+
+from zeep import Client
+
+
+def test_factory_namespace():
+    client = Client('tests/wsdl_files/soap.wsdl')
+    factory = client.type_factory('http://example.com/stockquote.xsd')
+    obj = factory.Address(NameFirst='Michael', NameLast='van Tellingen')
+    assert obj.NameFirst == 'Michael'
+    assert obj.NameLast == 'van Tellingen'
+
+
+def test_factory_ns_auto_prefix():
+    client = Client('tests/wsdl_files/soap.wsdl')
+    factory = client.type_factory('ns0')
+    obj = factory.Address(NameFirst='Michael', NameLast='van Tellingen')
+    assert obj.NameFirst == 'Michael'
+    assert obj.NameLast == 'van Tellingen'
+
+
+def test_factory_ns_custom_prefix():
+    client = Client('tests/wsdl_files/soap.wsdl')
+    client.set_ns_prefix('sq', 'http://example.com/stockquote.xsd')
+    factory = client.type_factory('sq')
+    obj = factory.Address(NameFirst='Michael', NameLast='van Tellingen')
+    assert obj.NameFirst == 'Michael'
+    assert obj.NameLast == 'van Tellingen'
+
+
+def test_factory_ns_unknown_prefix():
+    client = Client('tests/wsdl_files/soap.wsdl')
+
+    with pytest.raises(ValueError):
+        client.type_factory('bla')
diff --git a/tests/test_helpers.py b/tests/test_helpers.py
index a3ddb06..7165a5f 100644
--- a/tests/test_helpers.py
+++ b/tests/test_helpers.py
@@ -1,6 +1,6 @@
 from lxml import etree
 
-from tests.utils import load_xml
+from tests.utils import assert_nodes_equal, load_xml
 from zeep import xsd
 from zeep.helpers import serialize_object
 
@@ -111,3 +111,39 @@ def test_nested_complex_types():
     assert isinstance(result, dict), type(result)
     assert isinstance(result['item'], dict), type(result['item'])
     assert result['item']['item_1'] == 'foo'
+
+
+def test_serialize_any_array():
+    custom_type = xsd.Element(
+        etree.QName('http://tests.python-zeep.org/', 'authentication'),
+        xsd.ComplexType(
+            xsd.Sequence([
+                xsd.Any(max_occurs=2),
+            ])
+        ))
+
+    any_obj = etree.Element('{http://tests.python-zeep.org}lxml')
+    etree.SubElement(any_obj, 'node').text = 'foo'
+
+    obj = custom_type(any_obj)
+
+    expected = """
+        <document>
+          <ns0:authentication xmlns:ns0="http://tests.python-zeep.org/">
+            <ns0:lxml xmlns:ns0="http://tests.python-zeep.org">
+              <node>foo</node>
+            </ns0:lxml>
+          </ns0:authentication>
+        </document>
+    """
+    node = etree.Element('document')
+    custom_type.render(node, obj)
+    assert_nodes_equal(expected, node)
+
+    schema = xsd.Schema()
+    obj = custom_type.parse(node.getchildren()[0], schema=schema)
+    result = serialize_object(obj)
+
+    assert result == {
+        '_value_1': [any_obj],
+    }
diff --git a/tests/test_main.py b/tests/test_main.py
new file mode 100644
index 0000000..de98d04
--- /dev/null
+++ b/tests/test_main.py
@@ -0,0 +1,31 @@
+from mock import patch
+from pretend import stub
+
+from zeep import __main__, client
+
+
+def test_main_no_args(monkeypatch):
+    def mock_init(self, *args, **kwargs):
+        self.wsdl = stub(dump=lambda: None)
+
+    monkeypatch.setattr(client.Client, '__init__', mock_init)
+    args = __main__.parse_arguments(['foo.wsdl'])
+    __main__.main(args)
+
+
+def test_main_extract_auth(monkeypatch):
+    def mock_init(self, *args, **kwargs):
+        self.wsdl = stub(dump=lambda: None)
+
+    monkeypatch.setattr(client.Client, '__init__', mock_init)
+
+    with patch.object(__main__, 'Transport', autospec=True) as mock_transport:
+        args = __main__.parse_arguments(
+            ['http://user:secret@tests.python-zeep.org/foo.wsdl'])
+
+        __main__.main(args)
+
+        assert mock_transport.call_count == 1
+
+        args, kwargs = mock_transport.call_args
+        assert kwargs['http_auth'] == ('user', 'secret')
diff --git a/tests/test_pprint.py b/tests/test_pprint.py
new file mode 100644
index 0000000..1c53780
--- /dev/null
+++ b/tests/test_pprint.py
@@ -0,0 +1,34 @@
+from zeep.xsd import printer
+
+
+def test_dict():
+    pprint = printer.PrettyPrinter()
+    data = {
+        'foo': 'bar',
+        'foo_2': 'bar',
+        'foo_3': 'bar',
+        'foo_4': {
+            'bar': '1',
+            'bar': {
+                'bala': 'qwe',
+            },
+            'x': [1, 2, 3, 4],
+            'y': [],
+        }
+    }
+    pprint.pformat(data)
+
+
+def test_list():
+    pprint = printer.PrettyPrinter()
+    data = [
+        {
+            'foo': 'bar',
+            'foo_2': 'bar',
+        },
+        {
+            'foo': 'bar',
+            'foo_2': 'bar',
+        },
+    ]
+    pprint.pformat(data)
diff --git a/tests/test_transports.py b/tests/test_transports.py
new file mode 100644
index 0000000..63f3e00
--- /dev/null
+++ b/tests/test_transports.py
@@ -0,0 +1,29 @@
+import pytest
+import requests_mock
+from pretend import stub
+
+from zeep import cache, transports
+
+
+ at pytest.mark.requests
+def test_default_cache():
+    transport = transports.Transport()
+    assert isinstance(transport.cache, cache.SqliteCache)
+
+
+ at pytest.mark.requests
+def test_no_cache():
+    transport = transports.Transport(cache=None)
+    assert transport.cache is None
+
+
+ at pytest.mark.requests
+def test_load():
+    cache = stub(get=lambda url: None, add=lambda url, content: None)
+    transport = transports.Transport(cache=cache)
+
+    with requests_mock.mock() as m:
+        m.get('http://tests.python-zeep.org/test.xml', text='x')
+        result = transport.load('http://tests.python-zeep.org/test.xml')
+
+        assert result == b'x'
diff --git a/tests/test_wsa.py b/tests/test_wsa.py
new file mode 100644
index 0000000..a53d990
--- /dev/null
+++ b/tests/test_wsa.py
@@ -0,0 +1,268 @@
+import uuid
+
+from pretend import stub
+from six import StringIO
+
+from tests.utils import DummyTransport, assert_nodes_equal
+from zeep import wsa, wsdl, Client
+
+
+def test_require_wsa(recwarn, monkeypatch):
+    monkeypatch.setattr(
+        uuid, 'uuid4', lambda: uuid.UUID('ada686f9-5995-4088-bea4-239f694b2eaf'))
+
+    wsdl_main = StringIO("""
+        <?xml version="1.0"?>
+        <wsdl:definitions
+          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+          xmlns:tns="http://tests.python-zeep.org/xsd-main"
+          xmlns:sec="http://tests.python-zeep.org/wsdl-secondary"
+          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+          xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
+          xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
+          targetNamespace="http://tests.python-zeep.org/xsd-main">
+          <wsdl:types>
+            <xsd:schema
+                targetNamespace="http://tests.python-zeep.org/xsd-main"
+                xmlns:tns="http://tests.python-zeep.org/xsd-main">
+              <xsd:element name="input" type="xsd:string"/>
+              <xsd:element name="input2" type="xsd:string"/>
+            </xsd:schema>
+          </wsdl:types>
+
+          <wsdl:message name="dummyRequest">
+            <wsdl:part name="response" element="tns:input"/>
+          </wsdl:message>
+          <wsdl:message name="dummyResponse">
+            <wsdl:part name="response" element="tns:input2"/>
+          </wsdl:message>
+
+          <wsdl:portType name="TestPortType">
+            <wsdl:operation name="TestOperation1">
+              <wsdl:input message="dummyRequest" wsaw:Action="urn:dummyRequest"/>
+              <wsdl:output message="dummyResponse"  wsaw:Action="urn:dummyResponse"/>
+            </wsdl:operation>
+          </wsdl:portType>
+
+          <wsdl:binding name="TestBinding" type="tns:TestPortType">
+            <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+            <wsdl:operation name="TestOperation1">
+              <soap:operation soapAction=""/>
+              <wsdl:input>
+                <soap:body use="literal"/>
+              </wsdl:input>
+              <wsdl:output>
+                <soap:body use="literal"/>
+              </wsdl:output>
+            </wsdl:operation>
+          </wsdl:binding>
+          <wsdl:service name="TestService">
+            <wsdl:documentation>Test service</wsdl:documentation>
+            <wsdl:port name="TestPortType" binding="tns:TestBinding">
+              <soap:address location="http://tests.python-zeep.org/test"/>
+            </wsdl:port>
+          </wsdl:service>
+        </wsdl:definitions>
+    """.strip())
+
+    client = stub(plugins=[], wsse=None)
+
+    transport = DummyTransport()
+    client = Client(wsdl_main, transport=transport)
+    binding = client.wsdl.services.get('TestService').ports.get('TestPortType').binding
+
+    envelope, headers = binding._create(
+        'TestOperation1',
+        args=['foo'],
+        kwargs={},
+        client=client,
+        options={'address': 'http://tests.python-zeep.org/test'})
+    expected = """
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header  xmlns:wsa="http://www.w3.org/2005/08/addressing">
+            <wsa:Action>urn:dummyRequest</wsa:Action>
+            <wsa:MessageID>urn:uuid:ada686f9-5995-4088-bea4-239f694b2eaf</wsa:MessageID>
+            <wsa:To>http://tests.python-zeep.org/test</wsa:To>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:input xmlns:ns0="http://tests.python-zeep.org/xsd-main">foo</ns0:input>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, envelope)
+
+
+def test_force_wsa(recwarn, monkeypatch):
+    monkeypatch.setattr(
+        uuid, 'uuid4', lambda: uuid.UUID('ada686f9-5995-4088-bea4-239f694b2eaf'))
+
+    wsdl_main = StringIO("""
+        <?xml version="1.0"?>
+        <wsdl:definitions
+          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+          xmlns:tns="http://tests.python-zeep.org/xsd-main"
+          xmlns:sec="http://tests.python-zeep.org/wsdl-secondary"
+          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+          xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
+          targetNamespace="http://tests.python-zeep.org/xsd-main">
+          <wsdl:types>
+            <xsd:schema
+                targetNamespace="http://tests.python-zeep.org/xsd-main"
+                xmlns:tns="http://tests.python-zeep.org/xsd-main">
+              <xsd:element name="input" type="xsd:string"/>
+              <xsd:element name="input2" type="xsd:string"/>
+            </xsd:schema>
+          </wsdl:types>
+
+          <wsdl:message name="dummyRequest">
+            <wsdl:part name="response" element="tns:input"/>
+          </wsdl:message>
+          <wsdl:message name="dummyResponse">
+            <wsdl:part name="response" element="tns:input2"/>
+          </wsdl:message>
+
+          <wsdl:portType name="TestPortType">
+            <wsdl:operation name="TestOperation1">
+              <wsdl:input message="dummyRequest"/>
+              <wsdl:output message="dummyResponse"/>
+            </wsdl:operation>
+          </wsdl:portType>
+
+          <wsdl:binding name="TestBinding" type="tns:TestPortType">
+            <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+            <wsdl:operation name="TestOperation1">
+              <soap:operation soapAction="urn:dummyRequest"/>
+              <wsdl:input>
+                <soap:body use="literal"/>
+              </wsdl:input>
+              <wsdl:output>
+                <soap:body use="literal"/>
+              </wsdl:output>
+            </wsdl:operation>
+          </wsdl:binding>
+          <wsdl:service name="TestService">
+            <wsdl:documentation>Test service</wsdl:documentation>
+            <wsdl:port name="TestPortType" binding="tns:TestBinding">
+              <soap:address location="http://tests.python-zeep.org/test"/>
+            </wsdl:port>
+          </wsdl:service>
+        </wsdl:definitions>
+    """.strip())
+
+    transport = DummyTransport()
+    client = Client(wsdl_main, transport=transport, plugins=[wsa.WsAddressingPlugin()])
+    binding = client.wsdl.services.get('TestService').ports.get('TestPortType').binding
+
+    envelope, headers = binding._create(
+        'TestOperation1',
+        args=['foo'],
+        kwargs={},
+        client=client,
+        options={'address': 'http://tests.python-zeep.org/test'})
+    expected = """
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header  xmlns:wsa="http://www.w3.org/2005/08/addressing">
+            <wsa:Action>urn:dummyRequest</wsa:Action>
+            <wsa:MessageID>urn:uuid:ada686f9-5995-4088-bea4-239f694b2eaf</wsa:MessageID>
+            <wsa:To>http://tests.python-zeep.org/test</wsa:To>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:input xmlns:ns0="http://tests.python-zeep.org/xsd-main">foo</ns0:input>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, envelope)
+
+
+def test_force_wsa_soap12(recwarn, monkeypatch):
+    monkeypatch.setattr(
+        uuid, 'uuid4', lambda: uuid.UUID('ada686f9-5995-4088-bea4-239f694b2eaf'))
+
+    wsdl_main = StringIO("""
+        <?xml version="1.0"?>
+        <wsdl:definitions
+          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+          xmlns:tns="http://tests.python-zeep.org/xsd-main"
+          xmlns:sec="http://tests.python-zeep.org/wsdl-secondary"
+          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/"
+          xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap12/"
+          targetNamespace="http://tests.python-zeep.org/xsd-main">
+          <wsdl:types>
+            <xsd:schema
+                targetNamespace="http://tests.python-zeep.org/xsd-main"
+                xmlns:tns="http://tests.python-zeep.org/xsd-main">
+              <xsd:element name="input" type="xsd:string"/>
+              <xsd:element name="input2" type="xsd:string"/>
+            </xsd:schema>
+          </wsdl:types>
+
+          <wsdl:message name="dummyRequest">
+            <wsdl:part name="response" element="tns:input"/>
+          </wsdl:message>
+          <wsdl:message name="dummyResponse">
+            <wsdl:part name="response" element="tns:input2"/>
+          </wsdl:message>
+
+          <wsdl:portType name="TestPortType">
+            <wsdl:operation name="TestOperation1">
+              <wsdl:input message="dummyRequest"/>
+              <wsdl:output message="dummyResponse"/>
+            </wsdl:operation>
+          </wsdl:portType>
+
+          <wsdl:binding name="TestBinding" type="tns:TestPortType">
+            <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+            <wsdl:operation name="TestOperation1">
+              <soap:operation soapAction="urn:dummyRequest"/>
+              <wsdl:input>
+                <soap:body use="literal"/>
+              </wsdl:input>
+              <wsdl:output>
+                <soap:body use="literal"/>
+              </wsdl:output>
+            </wsdl:operation>
+          </wsdl:binding>
+          <wsdl:service name="TestService">
+            <wsdl:documentation>Test service</wsdl:documentation>
+            <wsdl:port name="TestPortType" binding="tns:TestBinding">
+              <soap:address location="http://tests.python-zeep.org/test"/>
+            </wsdl:port>
+          </wsdl:service>
+        </wsdl:definitions>
+    """.strip())
+
+    client = stub(plugins=[wsa.WsAddressingPlugin()], wsse=None)
+
+    transport = DummyTransport()
+    doc = wsdl.Document(wsdl_main, transport)
+    binding = doc.services.get('TestService').ports.get('TestPortType').binding
+
+    envelope, headers = binding._create(
+        'TestOperation1',
+        args=['foo'],
+        kwargs={},
+        client=client,
+        options={'address': 'http://tests.python-zeep.org/test'})
+    expected = """
+        <soap-env:Envelope
+            xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope">
+          <soap-env:Header  xmlns:wsa="http://www.w3.org/2005/08/addressing">
+            <wsa:Action>urn:dummyRequest</wsa:Action>
+            <wsa:MessageID>urn:uuid:ada686f9-5995-4088-bea4-239f694b2eaf</wsa:MessageID>
+            <wsa:To>http://tests.python-zeep.org/test</wsa:To>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:input xmlns:ns0="http://tests.python-zeep.org/xsd-main">foo</ns0:input>
+
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, envelope)
+
+    assert headers['Content-Type'] == (
+        'application/soap+xml; charset=utf-8; action="urn:dummyRequest"')
diff --git a/tests/test_wsdl_arrays.py b/tests/test_wsdl_arrays.py
new file mode 100644
index 0000000..f6ad722
--- /dev/null
+++ b/tests/test_wsdl_arrays.py
@@ -0,0 +1,360 @@
+import io
+
+from lxml import etree
+
+from tests.utils import DummyTransport, assert_nodes_equal, load_xml
+from zeep import xsd
+
+
+def get_transport():
+    transport = DummyTransport()
+    transport.bind(
+        'http://schemas.xmlsoap.org/soap/encoding/',
+        load_xml(io.open('tests/wsdl_files/soap-enc.xsd', 'r').read().encode('utf-8')))
+    return transport
+
+
+def test_simple_type():
+    schema = xsd.Schema(load_xml("""
+    <xsd:schema
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+        targetNamespace="http://tests.python-zeep.org/tns">
+      <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
+      <xsd:complexType name="ArrayOfString">
+        <xsd:complexContent>
+          <xsd:restriction base="SOAP-ENC:Array">
+            <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="xsd:string[]"/>
+          </xsd:restriction>
+        </xsd:complexContent>
+      </xsd:complexType>
+    </xsd:schema>
+    """), transport=get_transport())
+
+    ArrayOfString = schema.get_type('ns0:ArrayOfString')
+    print(ArrayOfString.__dict__)
+
+    value = ArrayOfString(['item', 'and', 'even', 'more', 'items'])
+
+    node = etree.Element('document')
+    ArrayOfString.render(node, value)
+
+    expected = """
+        <document>
+            <item xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">item</item>
+            <item xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">and</item>
+            <item xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">even</item>
+            <item xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">more</item>
+            <item xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">items</item>
+        </document>
+    """  # noqa
+
+    assert_nodes_equal(expected, node)
+
+
+def test_complex_type():
+    schema = xsd.Schema(load_xml("""
+    <xsd:schema
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+        xmlns:tns="http://tests.python-zeep.org/tns"
+        targetNamespace="http://tests.python-zeep.org/tns">
+      <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
+
+      <xsd:complexType name="ArrayObject">
+        <xsd:sequence>
+          <xsd:element name="attr_1" type="xsd:string"/>
+          <xsd:element name="attr_2" type="xsd:string"/>
+        </xsd:sequence>
+      </xsd:complexType>
+      <xsd:complexType name="ArrayOfObject">
+        <xsd:complexContent>
+          <xsd:restriction base="SOAP-ENC:Array">
+            <xsd:sequence>
+              <xsd:element name="obj" type="tns:ArrayObject" minOccurs="0" maxOccurs="unbounded"/>
+            </xsd:sequence>
+            <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="tns:ArrayObject[]"/>
+          </xsd:restriction>
+        </xsd:complexContent>
+      </xsd:complexType>
+    </xsd:schema>
+    """), transport=get_transport())
+
+    ArrayOfObject = schema.get_type('ns0:ArrayOfObject')
+    ArrayObject = schema.get_type('ns0:ArrayObject')
+
+    value = ArrayOfObject([
+        ArrayObject(attr_1='attr-1', attr_2='attr-2'),
+        ArrayObject(attr_1='attr-3', attr_2='attr-4'),
+        ArrayObject(attr_1='attr-5', attr_2='attr-6'),
+    ])
+
+    node = etree.Element('document')
+    ArrayOfObject.render(node, value)
+
+    expected = """
+        <document>
+            <obj>
+                <attr_1>attr-1</attr_1>
+                <attr_2>attr-2</attr_2>
+            </obj>
+            <obj>
+                <attr_1>attr-3</attr_1>
+                <attr_2>attr-4</attr_2>
+            </obj>
+            <obj>
+                <attr_1>attr-5</attr_1>
+                <attr_2>attr-6</attr_2>
+            </obj>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_complex_type_without_name():
+    schema = xsd.Schema(load_xml("""
+    <xsd:schema
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+        xmlns:tns="http://tests.python-zeep.org/tns"
+        targetNamespace="http://tests.python-zeep.org/tns">
+      <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
+
+      <xsd:complexType name="ArrayObject">
+        <xsd:sequence>
+          <xsd:element name="attr_1" type="xsd:string"/>
+          <xsd:element name="attr_2" type="xsd:string"/>
+        </xsd:sequence>
+      </xsd:complexType>
+      <xsd:complexType name="ArrayOfObject">
+        <xsd:complexContent>
+          <xsd:restriction base="SOAP-ENC:Array">
+            <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="tns:ArrayObject[]"/>
+          </xsd:restriction>
+        </xsd:complexContent>
+      </xsd:complexType>
+    </xsd:schema>
+    """), transport=get_transport())
+
+    ArrayOfObject = schema.get_type('ns0:ArrayOfObject')
+    ArrayObject = schema.get_type('ns0:ArrayObject')
+
+    value = ArrayOfObject([
+        ArrayObject(attr_1='attr-1', attr_2='attr-2'),
+        ArrayObject(attr_1='attr-3', attr_2='attr-4'),
+        ArrayObject(attr_1='attr-5', attr_2='attr-6'),
+    ])
+
+    node = etree.Element('document')
+    ArrayOfObject.render(node, value)
+
+    expected = """
+        <document>
+            <ArrayObject>
+                <attr_1>attr-1</attr_1>
+                <attr_2>attr-2</attr_2>
+            </ArrayObject>
+            <ArrayObject>
+                <attr_1>attr-3</attr_1>
+                <attr_2>attr-4</attr_2>
+            </ArrayObject>
+            <ArrayObject>
+                <attr_1>attr-5</attr_1>
+                <attr_2>attr-6</attr_2>
+            </ArrayObject>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_soap_array_parse_remote_ns():
+    transport = DummyTransport()
+    transport.bind(
+        'http://schemas.xmlsoap.org/soap/encoding/',
+        load_xml(io.open('tests/wsdl_files/soap-enc.xsd', 'r').read().encode('utf-8')))
+
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+          xmlns:tns="http://tests.python-zeep.org/"
+          xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
+          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          targetNamespace="http://tests.python-zeep.org/"
+          elementFormDefault="qualified">
+          <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
+          <xsd:simpleType name="CountryCodeType">
+            <xsd:restriction base="xsd:string">
+              <xsd:length value="2"/>
+              <xsd:pattern value="[a-zA-Z]{2}"/>
+            </xsd:restriction>
+          </xsd:simpleType>
+          <xsd:complexType name="CountryItemType">
+            <xsd:sequence>
+              <xsd:element name="code" type="tns:CountryCodeType"/>
+              <xsd:element name="name" type="xsd:string"/>
+            </xsd:sequence>
+          </xsd:complexType>
+          <xsd:complexType name="CountriesArrayType">
+            <xsd:complexContent>
+              <xsd:restriction base="soapenc:Array">
+                <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="tns:CountryItemType[]"/>
+              </xsd:restriction>
+            </xsd:complexContent>
+          </xsd:complexType>
+          <xsd:element name="countries" type="tns:CountriesArrayType"/>
+        </xsd:schema>
+    """), transport)
+
+    doc = load_xml("""
+      <countries
+            SOAP-ENC:arrayType="ns1:CountryItemType[1]"
+            xsi:type="ns1:CountriesArrayType"
+            xmlns:ns1="http://tests.python-zeep.org/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+        <item xsi:type="ns1:CountryItemType">
+          <code xsi:type="ns1:CountryCodeType">NL</code>
+          <name xsi:type="xsd:string">The Netherlands</name>
+        </item>
+      </countries>
+    """)
+
+    elm = schema.get_element('ns0:countries')
+    data = elm.parse(doc, schema)
+
+    assert data._value_1[0].code == 'NL'
+    assert data._value_1[0].name == 'The Netherlands'
+
+
+def test_wsdl_array_type():
+    transport = DummyTransport()
+    transport.bind(
+        'http://schemas.xmlsoap.org/soap/encoding/',
+        load_xml(io.open('tests/wsdl_files/soap-enc.xsd', 'r').read().encode('utf-8')))
+
+    schema = xsd.Schema(load_xml("""
+        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                    xmlns:tns="http://tests.python-zeep.org/"
+                    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+                    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                    targetNamespace="http://tests.python-zeep.org/"
+                    elementFormDefault="qualified">
+          <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
+          <xsd:complexType name="array">
+            <xsd:complexContent>
+              <xsd:restriction base="SOAP-ENC:Array">
+                <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="tns:base[]"/>
+              </xsd:restriction>
+            </xsd:complexContent>
+          </xsd:complexType>
+          <xsd:complexType name="base">
+            <xsd:sequence>
+              <xsd:element minOccurs="0" name="item_1" type="xsd:string"/>
+              <xsd:element minOccurs="0" name="item_2" type="xsd:string"/>
+            </xsd:sequence>
+          </xsd:complexType>
+          <xsd:element name="array" type="tns:array"/>
+        </xsd:schema>
+    """), transport)
+    array_elm = schema.get_element('{http://tests.python-zeep.org/}array')
+
+    item_type = schema.get_type('{http://tests.python-zeep.org/}base')
+    item_1 = item_type(item_1='foo_1', item_2='bar_1')
+    item_2 = item_type(item_1='foo_2', item_2='bar_2')
+
+    # array = array_elm([
+    #     xsd.AnyObject(item_type, item_1),
+    #     xsd.AnyObject(item_type, item_2),
+    # ])
+
+    array = array_elm([item_1, item_2])
+    node = etree.Element('document')
+    assert array_elm.signature() == (
+        '_value_1: base[], arrayType: xsd:string, offset: arrayCoordinate, ' +
+        'id: xsd:ID, href: xsd:anyURI, _attr_1: {}')
+    array_elm.render(node, array)
+    expected = """
+        <document>
+            <ns0:array xmlns:ns0="http://tests.python-zeep.org/">
+                <base>
+                    <ns0:item_1>foo_1</ns0:item_1>
+                    <ns0:item_2>bar_1</ns0:item_2>
+                </base>
+                <base>
+                    <ns0:item_1>foo_2</ns0:item_1>
+                    <ns0:item_2>bar_2</ns0:item_2>
+                </base>
+            </ns0:array>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_soap_array_parse():
+    transport = DummyTransport()
+    transport.bind(
+        'http://schemas.xmlsoap.org/soap/encoding/',
+        load_xml(io.open('tests/wsdl_files/soap-enc.xsd', 'r').read().encode('utf-8')))
+
+    schema = xsd.Schema(load_xml("""
+    <?xml version="1.0"?>
+    <schema xmlns="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+      <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
+      <complexType name="FlagDetailsStruct">
+          <sequence>
+              <element name="Name">
+                  <simpleType>
+                      <restriction base="string">
+                          <maxLength value="512"/>
+                      </restriction>
+                  </simpleType>
+              </element>
+              <element name="Value" type="string"/>
+          </sequence>
+      </complexType>
+      <complexType name="FlagDetailsList">
+          <complexContent>
+              <restriction base="soapenc:Array">
+                  <sequence>
+                      <element
+                        name="FlagDetailsStruct" type="tns:FlagDetailsStruct"
+                        minOccurs="0" maxOccurs="unbounded"/>
+                  </sequence>
+                  <attribute ref="soapenc:arrayType" use="required"/>
+              </restriction>
+          </complexContent>
+      </complexType>
+      <element name="FlagDetailsList" type="tns:FlagDetailsList"/>
+    </schema>
+    """), transport)
+
+    doc = load_xml("""
+         <FlagDetailsList xmlns="http://tests.python-zeep.org/">
+            <FlagDetailsStruct>
+               <Name>flag1</Name>
+               <Value>value1</Value>
+            </FlagDetailsStruct>
+            <FlagDetailsStruct>
+               <Name>flag2</Name>
+               <Value>value2</Value>
+            </FlagDetailsStruct>
+         </FlagDetailsList>
+    """)
+
+    elm = schema.get_element('ns0:FlagDetailsList')
+    data = elm.parse(doc, schema)
+    assert data.FlagDetailsStruct[0].Name == 'flag1'
+    assert data.FlagDetailsStruct[0].Value == 'value1'
+    assert data.FlagDetailsStruct[1].Name == 'flag2'
+    assert data.FlagDetailsStruct[1].Value == 'value2'
diff --git a/tests/test_wsdl_messages_document.py b/tests/test_wsdl_messages_document.py
new file mode 100644
index 0000000..5aa18a7
--- /dev/null
+++ b/tests/test_wsdl_messages_document.py
@@ -0,0 +1,1271 @@
+from lxml import etree
+from six import StringIO
+
+from tests.utils import assert_nodes_equal, load_xml
+from zeep import xsd
+from zeep.wsdl import wsdl
+
+
+def test_parse():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns">
+          <xsd:element name="Request" type="xsd:string"/>
+          <xsd:element name="Response" type="xsd:string"/>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+      <message name="Output">
+        <part element="tns:Response"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:body use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.body.signature() == 'xsd:string'
+    assert operation.input.header.signature() == ''
+    assert operation.input.envelope.signature() == 'body: xsd:string, header: {}'
+    assert operation.input.signature(as_output=False) == 'xsd:string'
+
+    assert operation.output.body.signature() == 'xsd:string'
+    assert operation.output.header.signature() == ''
+    assert operation.output.envelope.signature() == 'body: xsd:string, header: {}'
+    assert operation.output.signature(as_output=True) == 'body: xsd:string, header: {}'
+
+
+def test_empty_input_parse():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns">
+          <xsd:element name="Request" type="xsd:string"/>
+          <xsd:element name="Response" type="xsd:string"/>
+        </xsd:schema>
+      </types>
+
+      <message name="Input"/>
+      <message name="Output">
+        <part element="tns:Response"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:body use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.body.signature() == ''
+    assert operation.input.header.signature() == ''
+    assert operation.input.envelope.signature() == 'body: {}, header: {}'
+    assert operation.input.signature(as_output=False) == ''
+
+
+def test_parse_with_header():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns">
+          <xsd:element name="Request" type="xsd:string"/>
+          <xsd:element name="RequestHeader" type="xsd:string"/>
+          <xsd:element name="Response" type="xsd:string"/>
+          <xsd:element name="ResponseHeader" type="xsd:string"/>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+        <part name="auth" element="tns:RequestHeader"/>
+      </message>
+      <message name="Output">
+        <part element="tns:Response"/>
+        <part name="auth" element="tns:ResponseHeader"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:header message="tns:Input" part="auth" use="literal" />
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:header message="tns:Output" part="auth" use="literal" />
+            <soap:body use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.body.signature() == 'xsd:string'
+    assert operation.input.header.signature() == 'auth: RequestHeader()'
+    assert operation.input.envelope.signature() == 'body: xsd:string, header: {auth: RequestHeader()}'  # noqa
+    assert operation.input.signature(as_output=False) == 'xsd:string, _soapheaders={auth: RequestHeader()}'  # noqa
+
+    assert operation.output.body.signature() == 'xsd:string'
+    assert operation.output.header.signature() == 'auth: ResponseHeader()'
+    assert operation.output.envelope.signature() == 'body: xsd:string, header: {auth: ResponseHeader()}'  # noqa
+    assert operation.output.signature(as_output=True) == 'body: xsd:string, header: {auth: ResponseHeader()}'  # noqa
+
+
+def test_parse_with_header_type():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns">
+          <xsd:element name="Request" type="xsd:string"/>
+          <xsd:simpleType name="RequestHeaderType">
+            <xsd:restriction base="xsd:string"/>
+          </xsd:simpleType>
+          <xsd:element name="Response" type="xsd:string"/>
+          <xsd:simpleType name="ResponseHeaderType">
+            <xsd:restriction base="xsd:string"/>
+          </xsd:simpleType>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+        <part name="auth" type="tns:RequestHeaderType"/>
+      </message>
+      <message name="Output">
+        <part element="tns:Response"/>
+        <part name="auth" type="tns:ResponseHeaderType"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:header message="tns:Input" part="auth" use="literal" />
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:header message="tns:Output" part="auth" use="literal" />
+            <soap:body use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.body.signature() == 'xsd:string'
+    assert operation.input.header.signature() == 'auth: RequestHeaderType'
+    assert operation.input.envelope.signature() == 'body: xsd:string, header: {auth: RequestHeaderType}'  # noqa
+    assert operation.input.signature(as_output=False) == 'xsd:string, _soapheaders={auth: RequestHeaderType}'  # noqa
+
+    assert operation.output.body.signature() == 'xsd:string'
+    assert operation.output.header.signature() == 'auth: ResponseHeaderType'
+    assert operation.output.envelope.signature() == 'body: xsd:string, header: {auth: ResponseHeaderType}'  # noqa
+    assert operation.output.signature(as_output=True) == 'body: xsd:string, header: {auth: ResponseHeaderType}'  # noqa
+
+
+
+
+
+def test_parse_with_header_other_message():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns">
+          <xsd:element name="Request" type="xsd:string"/>
+          <xsd:element name="RequestHeader" type="xsd:string"/>
+        </xsd:schema>
+      </types>
+
+      <message name="InputHeader">
+        <part name="header" element="tns:RequestHeader"/>
+      </message>
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:header message="tns:InputHeader" part="header" use="literal" />
+            <soap:body use="literal"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.header.signature() == 'header: RequestHeader()'
+    assert operation.input.body.signature() == 'xsd:string'
+
+    header = root.types.get_element(
+        '{http://tests.python-zeep.org/tns}RequestHeader'
+    )('foo')
+    serialized = operation.input.serialize(
+        'ah1', _soapheaders={'header': header})
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header>
+            <ns0:RequestHeader xmlns:ns0="http://tests.python-zeep.org/tns">foo</ns0:RequestHeader>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:Request xmlns:ns0="http://tests.python-zeep.org/tns">ah1</ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
+def test_serialize():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    serialized = operation.input.serialize(arg1='ah1', arg2='ah2')
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Body>
+            <ns0:Request xmlns:ns0="http://tests.python-zeep.org/tns">
+              <ns0:arg1>ah1</ns0:arg1>
+              <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
+def test_serialize_with_header():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="Authentication">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="username" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+        <part element="tns:Authentication" name="auth"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+            <soap:header message="tns:Input" part="auth" use="literal"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    AuthHeader = root.types.get_element('{http://tests.python-zeep.org/tns}Authentication')
+    auth_header = AuthHeader(username='mvantellingen')
+
+    serialized = operation.input.serialize(
+        arg1='ah1', arg2='ah2', _soapheaders=[auth_header])
+    serialized = operation.input.serialize(
+        arg1='ah1', arg2='ah2', _soapheaders=[auth_header])
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header>
+            <ns0:Authentication xmlns:ns0="http://tests.python-zeep.org/tns">
+              <ns0:username>mvantellingen</ns0:username>
+            </ns0:Authentication>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:Request xmlns:ns0="http://tests.python-zeep.org/tns">
+              <ns0:arg1>ah1</ns0:arg1>
+              <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
+def test_serialize_with_headers_simple():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="Authentication">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="username" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+        <part element="tns:Authentication" name="Header"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+            <soap:header message="tns:Input" part="Header" use="literal"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    header = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Element('{http://www.w3.org/2005/08/addressing}Action', xsd.String()),
+            xsd.Element('{http://www.w3.org/2005/08/addressing}To', xsd.String()),
+        ])
+    )
+    header_value = header(Action='doehet', To='server')
+    serialized = operation.input.serialize(
+        arg1='ah1', arg2='ah2',
+        _soapheaders=[header_value])
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header>
+            <ns0:Action xmlns:ns0="http://www.w3.org/2005/08/addressing">doehet</ns0:Action>
+            <ns1:To xmlns:ns1="http://www.w3.org/2005/08/addressing">server</ns1:To>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:Request xmlns:ns0="http://tests.python-zeep.org/tns">
+              <ns0:arg1>ah1</ns0:arg1>
+              <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
+def test_serialize_with_header_and_custom_mixed():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="Authentication">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="username" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+        <part element="tns:Authentication" name="Header"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+            <soap:header message="tns:Input" part="Header" use="literal"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    header = root.types.get_element(
+        '{http://tests.python-zeep.org/tns}Authentication'
+    )
+    header_1 = header(username='mvantellingen')
+
+    header = xsd.Element(
+        '{http://test.python-zeep.org/custom}custom',
+        xsd.ComplexType([
+            xsd.Element('{http://test.python-zeep.org/custom}foo', xsd.String()),
+        ])
+    )
+    header_2 = header(foo='bar')
+
+    serialized = operation.input.serialize(
+        arg1='ah1', arg2='ah2',
+        _soapheaders=[header_1, header_2])
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header>
+            <ns0:Authentication xmlns:ns0="http://tests.python-zeep.org/tns">
+              <ns0:username>mvantellingen</ns0:username>
+            </ns0:Authentication>
+            <ns1:custom xmlns:ns1="http://test.python-zeep.org/custom">
+              <ns1:foo>bar</ns1:foo>
+            </ns1:custom>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:Request xmlns:ns0="http://tests.python-zeep.org/tns">
+              <ns0:arg1>ah1</ns0:arg1>
+              <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
+def test_serializer_with_header_custom_elm():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    header = xsd.Element(
+        '{http://test.python-zeep.org/custom}auth',
+        xsd.ComplexType([
+            xsd.Element('{http://test.python-zeep.org/custom}username', xsd.String()),
+        ])
+    )
+
+    serialized = operation.input.serialize(
+        arg1='ah1', arg2='ah2', _soapheaders=[header(username='mvantellingen')])
+
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header>
+            <ns0:auth xmlns:ns0="http://test.python-zeep.org/custom">
+              <ns0:username>mvantellingen</ns0:username>
+            </ns0:auth>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:Request xmlns:ns0="http://tests.python-zeep.org/tns">
+              <ns0:arg1>ah1</ns0:arg1>
+              <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
+def test_serializer_with_header_custom_xml():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    header_value = etree.Element('{http://test.python-zeep.org/custom}auth')
+    etree.SubElement(
+        header_value, '{http://test.python-zeep.org/custom}username'
+    ).text = 'mvantellingen'
+
+    serialized = operation.input.serialize(
+        arg1='ah1', arg2='ah2', _soapheaders=[header_value])
+
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header>
+            <ns0:auth xmlns:ns0="http://test.python-zeep.org/custom">
+              <ns0:username>mvantellingen</ns0:username>
+            </ns0:auth>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:Request xmlns:ns0="http://tests.python-zeep.org/tns">
+              <ns0:arg1>ah1</ns0:arg1>
+              <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
+def test_deserialize():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+      <message name="Output">
+        <part element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:body use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    response_body = load_xml("""
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:ns0="http://tests.python-zeep.org/tns"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Body>
+            <ns0:Request>
+              <ns0:arg1>ah1</ns0:arg1>
+              <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)
+    result = operation.process_reply(response_body)
+    assert result.arg1 == 'ah1'
+    assert result.arg2 == 'ah2'
+
+
+def test_deserialize_no_content():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request" type="xsd:string"/>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+      <message name="Output">
+        <part element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:body use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    response_body = load_xml("""
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:ns0="http://tests.python-zeep.org/tns"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Body>
+            <ns0:Request/>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)
+    result = operation.process_reply(response_body)
+    assert result is None
+
+
+def test_deserialize_choice():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:choice>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+      <message name="Output">
+        <part element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:body use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    response_body = load_xml("""
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:ns0="http://tests.python-zeep.org/tns"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Body>
+            <ns0:Request>
+              <ns0:arg1>ah1</ns0:arg1>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)
+    result = operation.process_reply(response_body)
+    assert result.arg1 == 'ah1'
+
+
+def test_deserialize_one_part():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+
+      <message name="Output">
+        <part element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:body use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    response_body = load_xml("""
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:ns0="http://tests.python-zeep.org/tns"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header>
+            <ns0:auth xmlns:ns0="http://test.python-zeep.org/custom">
+              <ns0:username>mvantellingen</ns0:username>
+            </ns0:auth>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:Request>
+              <ns0:arg1>ah1</ns0:arg1>
+              <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)  # noqa
+
+    serialized = operation.process_reply(response_body)
+    assert serialized.arg1 == 'ah1'
+    assert serialized.arg2 == 'ah2'
+
+
+def test_deserialize_with_headers():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request1">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+
+          <xsd:element name="Request2">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+
+          <xsd:element name="Header1">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="username" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="Header2" type="xsd:string"/>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request1"/>
+      </message>
+
+      <message name="Output">
+        <part element="tns:Request1" name="request_1"/>
+        <part element="tns:Request2" name="request_2"/>
+        <part element="tns:Header1" name="header_1"/>
+        <part element="tns:Header2" name="header_2"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:body use="literal"/>
+            <soap:header message="tns:Output" part="header_1" use="literal">
+              <soap:headerfault message="tns:OutputFault"
+                    part="header_1_fault" use="literal"/>
+            </soap:header>
+            <soap:header message="tns:Output" part="header_2" use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    response_body = load_xml("""
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:ns0="http://tests.python-zeep.org/tns"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Header>
+            <ns0:Header1>
+              <ns0:username>mvantellingen</ns0:username>
+            </ns0:Header1>
+            <ns0:Header2>foo</ns0:Header2>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:Request1>
+              <ns0:arg1>ah1</ns0:arg1>
+            </ns0:Request1>
+            <ns0:Request2>
+              <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request2>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)  # noqa
+
+    serialized = operation.process_reply(response_body)
+
+    assert operation.output.signature(as_output=True) == (
+        'body: {request_1: Request1(), request_2: Request2()}, header: {header_1: Header1(), header_2: Header2()}')  # noqa
+    assert serialized.body.request_1.arg1 == 'ah1'
+    assert serialized.body.request_2.arg2 == 'ah2'
+    assert serialized.header.header_1.username == 'mvantellingen'
+
+
+def test_serialize_any_type():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns"
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:anyType"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    serialized = operation.input.serialize(
+        arg1=xsd.AnyObject(xsd.String(), 'ah1'))
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Body>
+            <ns0:Request xmlns:ns0="http://tests.python-zeep.org/tns">
+              <ns0:arg1
+                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                xsi:type="xs:string">ah1</ns0:arg1>
+            </ns0:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+    deserialized = operation.input.deserialize(serialized.content)
+
+    assert deserialized == 'ah1'
diff --git a/tests/test_wsdl_messages_http.py b/tests/test_wsdl_messages_http.py
new file mode 100644
index 0000000..aa40d25
--- /dev/null
+++ b/tests/test_wsdl_messages_http.py
@@ -0,0 +1,390 @@
+from six import StringIO
+
+from tests.utils import assert_nodes_equal, load_xml
+from zeep.wsdl import wsdl
+
+
+##
+# URLEncoded Message
+#
+def test_urlencoded_serialize():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
+                 xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+
+      <message name="Input">
+        <part name="arg1" type="xsd:string"/>
+        <part name="arg2" type="xsd:string"/>
+      </message>
+      <message name="Output">
+        <part name="Body" type="xsd:string"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <http:binding verb="POST"/>
+        <operation name="TestOperation">
+          <http:operation location="test-operation"/>
+          <input>
+            <http:urlEncoded/>
+          </input>
+          <output>
+            <mime:mimeXml part="Body"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.body.signature() == 'arg1: xsd:string, arg2: xsd:string'
+    assert operation.input.signature(as_output=False) == 'arg1: xsd:string, arg2: xsd:string'
+
+    assert operation.output.body.signature() == 'Body: xsd:string'
+    assert operation.output.signature(as_output=True) == 'xsd:string'
+
+    serialized = operation.input.serialize(arg1='ah1', arg2='ah2')
+    assert serialized.headers == {'Content-Type': 'text/xml; charset=utf-8'}
+    assert serialized.path == 'test-operation'
+    assert serialized.content == {'arg1': 'ah1', 'arg2': 'ah2'}
+
+
+##
+# URLReplacement Message
+#
+def test_urlreplacement_serialize():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
+                 xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+
+      <message name="Input">
+        <part name="arg1" type="xsd:string"/>
+        <part name="arg2" type="xsd:string"/>
+      </message>
+      <message name="Output">
+        <part name="Body" type="xsd:string"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <http:binding verb="POST"/>
+        <operation name="TestOperation">
+          <http:operation location="test-operation/(arg1)/(arg2)/"/>
+          <input>
+            <http:urlReplacement/>
+          </input>
+          <output>
+            <mime:mimeXml part="Body"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.body.signature() == 'arg1: xsd:string, arg2: xsd:string'
+    assert operation.input.signature(as_output=False) == 'arg1: xsd:string, arg2: xsd:string'
+
+    assert operation.output.body.signature() == 'Body: xsd:string'
+    assert operation.output.signature(as_output=True) == 'xsd:string'
+
+    serialized = operation.input.serialize(arg1='ah1', arg2='ah2')
+    assert serialized.headers == {'Content-Type': 'text/xml; charset=utf-8'}
+    assert serialized.path == 'test-operation/ah1/ah2/'
+    assert serialized.content == ''
+
+
+##
+# MimeContent Message
+#
+def test_mime_content_serialize_form_urlencoded():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
+                 xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+
+      <message name="Input">
+        <part name="arg1" type="xsd:string"/>
+        <part name="arg2" type="xsd:string"/>
+      </message>
+      <message name="Output">
+        <part name="Body" type="xsd:string"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <http:binding verb="POST"/>
+        <operation name="TestOperation">
+          <http:operation location="test-operation"/>
+          <input>
+            <mime:content type="application/x-www-form-urlencoded"/>
+          </input>
+          <output>
+            <mime:mimeXml part="Body"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.body.signature() == 'arg1: xsd:string, arg2: xsd:string'
+    assert operation.input.signature(as_output=False) == 'arg1: xsd:string, arg2: xsd:string'
+
+    assert operation.output.body.signature() == 'Body: xsd:string'
+    assert operation.output.signature(as_output=True) == 'xsd:string'
+
+    serialized = operation.input.serialize(arg1='ah1', arg2='ah2')
+    assert serialized.headers == {'Content-Type': 'application/x-www-form-urlencoded'}
+    assert serialized.path == 'test-operation'
+    assert serialized.content == 'arg1=ah1&arg2=ah2'
+
+
+def test_mime_content_serialize_text_xml():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
+                 xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+
+      <message name="Input">
+        <part name="arg1" type="xsd:string"/>
+        <part name="arg2" type="xsd:string"/>
+      </message>
+      <message name="Output">
+        <part name="Body" type="xsd:string"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <http:binding verb="POST"/>
+        <operation name="TestOperation">
+          <http:operation location="test-operation"/>
+          <input>
+            <mime:content type="text/xml"/>
+          </input>
+          <output>
+            <mime:mimeXml part="Body"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.body.signature() == 'arg1: xsd:string, arg2: xsd:string'
+    assert operation.input.signature(as_output=False) == 'arg1: xsd:string, arg2: xsd:string'
+
+    assert operation.output.body.signature() == 'Body: xsd:string'
+    assert operation.output.signature(as_output=True) == 'xsd:string'
+
+    serialized = operation.input.serialize(arg1='ah1', arg2='ah2')
+    assert serialized.headers == {'Content-Type': 'text/xml'}
+    assert serialized.path == 'test-operation'
+    assert_nodes_equal(
+        load_xml(serialized.content),
+        load_xml("<TestOperation><arg1>ah1</arg1><arg2>ah2</arg2></TestOperation>"))
+
+
+def test_mime_content_no_parts():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
+                 xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+
+      <message name="Input"/>
+      <message name="Output">
+        <part name="Body" type="xsd:string"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <http:binding verb="POST"/>
+        <operation name="TestOperation">
+          <http:operation location="/test-operation"/>
+          <input>
+            <mime:content type="application/x-www-form-urlencoded"/>
+          </input>
+          <output>
+            <mime:mimeXml part="Body"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.signature() == ''
+
+    serialized = operation.input.serialize()
+    assert serialized.content == ''
+
+
+def test_mime_xml_deserialize():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
+                 xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <types>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/tns"
+            targetNamespace="http://tests.python-zeep.org/tns"
+                elementFormDefault="qualified">
+          <xsd:element name="response">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="item_1" type="xsd:string"/>
+                <xsd:element name="item_2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part name="arg1" type="xsd:string"/>
+        <part name="arg2" type="xsd:string"/>
+      </message>
+      <message name="Output">
+        <part name="Body" element="tns:response"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <http:binding verb="POST"/>
+        <operation name="TestOperation">
+          <http:operation location="/test-operation"/>
+          <input>
+            <mime:content type="application/x-www-form-urlencoded"/>
+          </input>
+          <output>
+            <mime:mimeXml part="Body"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.signature() == 'arg1: xsd:string, arg2: xsd:string'
+    assert operation.output.signature(as_output=True) == (
+        'item_1: xsd:string, item_2: xsd:string')
+
+    node = """
+        <response xmlns="http://tests.python-zeep.org/tns">
+          <item_1>foo</item_1>
+          <item_2>bar</item_2>
+        </response>
+    """.strip()
+
+    serialized = operation.output.deserialize(node)
+    assert serialized.item_1 == 'foo'
+    assert serialized.item_2 == 'bar'
+
+
+def test_mime_multipart_parse():
+    load_xml("""
+        <output
+            xmlns="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/">
+          <mime:multipartRelated>
+              <mime:part>
+                  <soap:body parts="body" use="literal"/>
+              </mime:part>
+              <mime:part>
+                  <mime:content part="test" type="text/html"/>
+              </mime:part>
+              <mime:part>
+                  <mime:content part="logo" type="image/gif"/>
+                  <mime:content part="logo" type="image/jpeg"/>
+              </mime:part>
+          </mime:multipartRelated>
+       </output>
+    """)
diff --git a/tests/test_wsdl_messages_rpc.py b/tests/test_wsdl_messages_rpc.py
new file mode 100644
index 0000000..123683d
--- /dev/null
+++ b/tests/test_wsdl_messages_rpc.py
@@ -0,0 +1,434 @@
+import io
+
+from six import StringIO
+
+from tests.utils import DummyTransport, assert_nodes_equal, load_xml
+from zeep.wsdl import wsdl
+
+
+def test_serialize():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+
+      <message name="Input">
+        <part name="arg1" type="xsd:string"/>
+        <part name="arg2" type="xsd:string"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="encoded"
+                       namespace="http://test.python-zeep.org/tests/rpc"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    assert operation.input.signature() == 'arg1: xsd:string, arg2: xsd:string'
+
+    serialized = operation.input.serialize(arg1='ah1', arg2='ah2')
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Body>
+            <ns0:TestOperation xmlns:ns0="http://test.python-zeep.org/tests/rpc">
+              <arg1>ah1</arg1>
+              <arg2>ah2</arg2>
+            </ns0:TestOperation>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
+def test_serialize_empty_input():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="tns:TestOperationRequests"/>
+        </operation>
+      </portType>
+
+      <message name="TestOperationRequests"/>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="encoded"
+                       namespace="http://test.python-zeep.org/tests/rpc"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    serialized = operation.input.serialize()
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Body>
+            <ns0:TestOperation xmlns:ns0="http://test.python-zeep.org/tests/rpc"/>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
+def test_deserialize():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+      <message name="Output">
+        <part name="result" type="xsd:string"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <output message="Output"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <output>
+            <soap:body use="encoded"
+                       namespace="http://test.python-zeep.org/tests/rpc"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    document = load_xml("""
+        <soap-env:Envelope
+          xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
+          <soap-env:Body>
+            <ns0:Output xmlns:ns0="http://test.python-zeep.org/tests/rpc">
+              <result>ah1</result>
+            </ns0:Output>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)
+    assert operation.output.signature(True) == 'body: {result: xsd:string}, header: {}'
+    result = operation.output.deserialize(document)
+    assert result == 'ah1'
+
+
+def test_wsdl_array_of_simple_types():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+        targetNamespace="http://tests.python-zeep.org/tns"
+        xmlns:tns="http://tests.python-zeep.org/tns"
+        xmlns:impl="http://tests.python-zeep.org/tns"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
+      <types>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://tests.python-zeep.org/tns">
+          <complexType name="ArrayOfString">
+            <complexContent>
+              <restriction base="soapenc:Array">
+                <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
+              </restriction>
+            </complexContent>
+          </complexType>
+        </schema>
+      </types>
+      <portType name="SimpleTypeArrayPortType">
+        <operation name="getSimpleArray">
+          <input message="tns:getSimpleArrayRequest"/>
+          <output message="tns:getSimpleArrayResponse"/>
+        </operation>
+      </portType>
+      <binding name="SimpleTypeArrayBinding" type="tns:SimpleTypeArrayPortType">
+        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="getSimpleArray">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="encoded" namespace="http://tests.python-zeep.org/tns" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+          </input>
+          <output>
+            <soap:body parts="return" use="encoded" namespace="http://tests.python-zeep.org/tns" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+          </output>
+        </operation>
+      </binding>
+      <message name="getSimpleArrayRequest"/>
+      <message name="getSimpleArrayResponse">
+        <part name="return" type="tns:ArrayOfString"/>
+      </message>
+    </definitions>
+    """.strip())  # noqa
+
+    transport = DummyTransport()
+    transport.bind(
+        'http://schemas.xmlsoap.org/soap/encoding/',
+        load_xml(io.open('tests/wsdl_files/soap-enc.xsd', 'r').read().encode('utf-8')))
+    root = wsdl.Document(wsdl_content, transport)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}SimpleTypeArrayBinding']
+    operation = binding.get('getSimpleArray')
+
+    document = load_xml("""
+    <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+        xmlns:ns1="http://tests.python-zeep.org/tns"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+      <SOAP-ENV:Body>
+        <ns1:getSimpleArrayResponse>
+            <return SOAP-ENC:arrayType="xsd:string[16]" xsi:type="ns1:ArrayOfString">
+                <item xsi:type="xsd:string">item</item>
+                <item xsi:type="xsd:string">and</item>
+                <item xsi:type="xsd:string">even</item>
+                <item xsi:type="xsd:string">more</item>
+                <item xsi:type="xsd:string">items</item>
+            </return>
+        </ns1:getSimpleArrayResponse>
+      </SOAP-ENV:Body>
+    </SOAP-ENV:Envelope>
+    """)
+
+    deserialized = operation.output.deserialize(document)
+    assert deserialized == ['item', 'and', 'even', 'more', 'items']
+
+
+def test_handle_incorrectly_qualified():
+    # Based on #176
+    wsdl_content = StringIO("""
+    <?xml version="1.0"?>
+    <wsdl:definitions
+        xmlns="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:tns="http://tests.python-zeep.org/tns"
+        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
+        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        targetNamespace="http://tests.python-zeep.org/tns">
+      <wsdl:message name="getResponse">
+        <wsdl:part name="getItemReturn" type="xsd:string"/>
+      </wsdl:message>
+      <wsdl:message name="getRequest"></wsdl:message>
+      <wsdl:portType name="Test">
+        <wsdl:operation name="getItem">
+          <wsdl:input message="tns:getRequest" name="getRequest"/>
+          <wsdl:output message="tns:getResponse" name="getResponse"/>
+        </wsdl:operation>
+      </wsdl:portType>
+      <wsdl:binding name="TestSoapBinding" type="tns:Test">
+        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <wsdl:operation name="getItem">
+          <soap:operation soapAction=""/>
+          <wsdl:input name="getRequest">
+            <soap:body
+                encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+                namespace="http://tests.python-zeep.org/tns" use="encoded"/>
+          </wsdl:input>
+          <wsdl:output name="getResponse">
+            <soap:body
+                encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+                namespace="http://tests.python-zeep.org/tns" use="encoded"/>
+          </wsdl:output>
+        </wsdl:operation>
+      </wsdl:binding>
+      <wsdl:service name="TestService">
+        <wsdl:port binding="tns:TestSoapBinding" name="Test">
+          <soap:address location="http://test.python-zeeo.org/rpc"/>
+        </wsdl:port>
+      </wsdl:service>
+    </wsdl:definitions>
+    """.strip())
+
+    transport = DummyTransport()
+    root = wsdl.Document(wsdl_content, transport)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestSoapBinding']
+    operation = binding.get('getItem')
+
+    document = load_xml("""
+    <soapenv:Envelope
+        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+      <soapenv:Body>
+        <ns1:getResponse
+            soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+            xmlns:ns1="http://tests.python-zeep.org/tns">
+          <ns1:getItemReturn xsi:type="xsd:string">foobar</ns1:getItemReturn>
+        </ns1:getResponse>
+      </soapenv:Body>
+    </soapenv:Envelope>
+    """)
+    deserialized = operation.output.deserialize(document)
+    assert deserialized == 'foobar'
+
+
+def test_deserialize_rpc_literal():
+    # Based on #219
+    wsdl_content = StringIO("""
+    <?xml version="1.0"?>
+    <wsdl:definitions
+        xmlns="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:tns="http://tests.python-zeep.org/tns"
+        xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
+        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        targetNamespace="http://tests.python-zeep.org/tns">
+
+      <wsdl:message name="getItemSoapIn"></wsdl:message>
+      <wsdl:message name="getItemSoapOut">
+        <wsdl:part name="getItemReturn" type="xsd:string"/>
+      </wsdl:message>
+
+      <wsdl:portType name="Test">
+        <wsdl:operation name="getItem">
+          <wsdl:input message="tns:getItemSoapIn"/>
+          <wsdl:output message="tns:getItemSoapOut"/>
+        </wsdl:operation>
+      </wsdl:portType>
+
+      <wsdl:binding name="TestSoapBinding" type="tns:Test">
+        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <wsdl:operation name="getItem">
+          <soap:operation soapAction=""/>
+          <wsdl:input>
+            <soap:body
+                encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+                namespace="http://tests.python-zeep.org/tns" use="encoded"/>
+          </wsdl:input>
+          <wsdl:output>
+            <soap:body
+                encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+                namespace="http://tests.python-zeep.org/tns" use="encoded"/>
+          </wsdl:output>
+        </wsdl:operation>
+      </wsdl:binding>
+      <wsdl:service name="TestService">
+        <wsdl:port binding="tns:TestSoapBinding" name="Test">
+          <soap:address location="http://test.python-zeeo.org/rpc"/>
+        </wsdl:port>
+      </wsdl:service>
+    </wsdl:definitions>
+    """.strip())
+
+    transport = DummyTransport()
+    root = wsdl.Document(wsdl_content, transport)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestSoapBinding']
+    operation = binding.get('getItem')
+
+    document = load_xml("""
+    <soapenv:Envelope
+        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+      <soapenv:Body>
+        <ns1:getItemResponse
+            soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+            xmlns:ns1="http://tests.python-zeep.org/tns">
+          <ns1:getItemReturn xsi:type="xsd:string">foobar</ns1:getItemReturn>
+        </ns1:getItemResponse>
+      </soapenv:Body>
+    </soapenv:Envelope>
+    """)
+    deserialized = operation.output.deserialize(document)
+    assert deserialized == 'foobar'
+
+
+def test_deserialize():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
+                 xmlns:tns="http://tests.python-zeep.org/tns"
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                 xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
+                 targetNamespace="http://tests.python-zeep.org/tns">
+
+
+      <message name="clearFoo">
+        <part name="code" type="xsd:string"/>
+      </message>
+      <message name="clearFooResponse"/>
+
+      <portType name="TestPortType">
+        <operation name="clearFoo">
+          <input wsam:Action="http://foo.services.example.com/Util/clearFooRequest" message="tns:clearFoo"/>
+          <output wsam:Action="http://foo.services.example.com/Util/clearFooResponse" message="tns:clearFooResponse"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="clearFoo">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal" namespace="http://foo.services.example.com/"/>
+          </input>
+          <output>
+            <soap:body use="literal" namespace="http://foo.services.example.com/"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('clearFoo')
+
+    document = load_xml("""
+        <?xml version="1.0" ?>
+        <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
+            <S:Body>
+                <ns2:clearFooResponse xmlns:ns2="http://foo.services.example.com/"/>
+            </S:Body>
+        </S:Envelope>
+    """)
+    result = operation.output.deserialize(document)
+    assert result is None
diff --git a/tests/test_wsdl_soap.py b/tests/test_wsdl_soap.py
new file mode 100644
index 0000000..04a9fc9
--- /dev/null
+++ b/tests/test_wsdl_soap.py
@@ -0,0 +1,110 @@
+from lxml import etree
+
+from tests.utils import load_xml
+from zeep.exceptions import Fault
+from zeep.wsdl import bindings
+
+
+def test_soap11_process_error():
+    response = load_xml("""
+        <soapenv:Envelope
+            xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:stoc="http://example.com/stockquote.xsd">
+          <soapenv:Body>
+            <soapenv:Fault>
+              <faultcode>fault-code</faultcode>
+              <faultstring>fault-string</faultstring>
+              <detail>
+                <e:myFaultDetails xmlns:e="http://myexample.org/faults">
+                  <e:message>detail-message</e:message>
+                  <e:errorcode>detail-code</e:errorcode>
+                </e:myFaultDetails>
+              </detail>
+            </soapenv:Fault>
+          </soapenv:Body>
+        </soapenv:Envelope>
+    """)
+    binding = bindings.Soap11Binding(
+        wsdl=None, name=None, port_name=None, transport=None,
+        default_style=None)
+
+    try:
+        binding.process_error(response, None)
+        assert False
+    except Fault as exc:
+        assert exc.message == 'fault-string'
+        assert exc.code == 'fault-code'
+        assert exc.actor is None
+        assert exc.subcodes is None
+        assert 'detail-message' in etree.tostring(exc.detail).decode('utf-8')
+
+
+def test_soap12_process_error():
+    response = """
+        <soapenv:Envelope
+            xmlns="http://example.com/example1"
+            xmlns:ex="http://example.com/example2"
+            xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
+          <soapenv:Body>
+            <soapenv:Fault>
+             <soapenv:Code>
+               <soapenv:Value>fault-code</soapenv:Value>
+               %s
+             </soapenv:Code>
+             <soapenv:Reason>
+              <soapenv:Text xml:lang="en-US">us-error</soapenv:Text>
+              <soapenv:Text xml:lang="nl-NL">nl-error</soapenv:Text>
+             </soapenv:Reason>
+             <soapenv:Detail>
+              <e:myFaultDetails
+                xmlns:e="http://myexample.org/faults" >
+                <e:message>Invalid credit card details</e:message>
+                <e:errorcode>999</e:errorcode>
+              </e:myFaultDetails>
+             </soapenv:Detail>
+           </soapenv:Fault>
+         </soapenv:Body>
+        </soapenv:Envelope>
+    """
+    subcode = """
+               <soapenv:Subcode>
+                 <soapenv:Value>%s</soapenv:Value>
+                 %s
+               </soapenv:Subcode>
+    """
+    binding = bindings.Soap12Binding(
+        wsdl=None, name=None, port_name=None, transport=None,
+        default_style=None)
+
+    try:
+        binding.process_error(load_xml(response % ""), None)
+        assert False
+    except Fault as exc:
+        assert exc.message == 'us-error'
+        assert exc.code == 'fault-code'
+        assert exc.subcodes == []
+
+    try:
+        binding.process_error(
+            load_xml(response % subcode % ("fault-subcode1", "")), None)
+        assert False
+    except Fault as exc:
+        assert exc.message == 'us-error'
+        assert exc.code == 'fault-code'
+        assert len(exc.subcodes) == 1
+        assert exc.subcodes[0].namespace == 'http://example.com/example1'
+        assert exc.subcodes[0].localname == 'fault-subcode1'
+
+    try:
+        binding.process_error(
+            load_xml(response % subcode % ("fault-subcode1", subcode % ("ex:fault-subcode2", ""))),
+            None)
+        assert False
+    except Fault as exc:
+        assert exc.message == 'us-error'
+        assert exc.code == 'fault-code'
+        assert len(exc.subcodes) == 2
+        assert exc.subcodes[0].namespace == 'http://example.com/example1'
+        assert exc.subcodes[0].localname == 'fault-subcode1'
+        assert exc.subcodes[1].namespace == 'http://example.com/example2'
+        assert exc.subcodes[1].localname == 'fault-subcode2'
diff --git a/tests/test_wsse_username.py b/tests/test_wsse_username.py
new file mode 100644
index 0000000..690b818
--- /dev/null
+++ b/tests/test_wsse_username.py
@@ -0,0 +1,238 @@
+import datetime
+import os
+
+import pytest
+import requests_mock
+from freezegun import freeze_time
+
+from tests.utils import assert_nodes_equal, load_xml
+from zeep import client
+from zeep.wsse.username import UsernameToken
+
+
+ at pytest.mark.requests
+def test_integration():
+    client_obj = client.Client(
+        'tests/wsdl_files/soap.wsdl',
+        wsse=UsernameToken('username', 'password'))
+
+    response = """
+    <?xml version="1.0"?>
+    <soapenv:Envelope
+        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
+        xmlns:stoc="http://example.com/stockquote.xsd">
+       <soapenv:Header/>
+       <soapenv:Body>
+          <stoc:TradePrice>
+             <price>120.123</price>
+          </stoc:TradePrice>
+       </soapenv:Body>
+    </soapenv:Envelope>
+    """.strip()
+
+    with requests_mock.mock() as m:
+        m.post('http://example.com/stockquote', text=response)
+        result = client_obj.service.GetLastTradePrice('foobar')
+        assert result == 120.123
+
+
+def test_password_text():
+    envelope = load_xml("""
+        <soap-env:Envelope
+            xmlns:ns0="http://example.com/stockquote.xsd"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        >
+          <soap-env:Body>
+            <ns0:TradePriceRequest>
+              <tickerSymbol>foobar</tickerSymbol>
+              <ns0:country/>
+            </ns0:TradePriceRequest>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)
+
+    token = UsernameToken('michael', 'geheim')
+    envelope, headers = token.sign(envelope, {})
+    expected = """
+        <soap-env:Envelope
+            xmlns:ns0="http://example.com/stockquote.xsd"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <soap-env:Header>
+            <ns0:Security xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+              <ns0:UsernameToken>
+                <ns0:Username>michael</ns0:Username>
+                <ns0:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">geheim</ns0:Password>
+              </ns0:UsernameToken>
+            </ns0:Security>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:TradePriceRequest>
+              <tickerSymbol>foobar</tickerSymbol>
+              <ns0:country/>
+            </ns0:TradePriceRequest>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """  # noqa
+    assert_nodes_equal(envelope, expected)
+
+
+ at freeze_time('2016-05-08 12:00:00')
+def test_password_digest(monkeypatch):
+    monkeypatch.setattr(os, 'urandom', lambda x: b'mocked-random')
+
+    envelope = load_xml("""
+        <soap-env:Envelope
+            xmlns:ns0="http://example.com/stockquote.xsd"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        >
+          <soap-env:Body>
+            <ns0:TradePriceRequest>
+              <tickerSymbol>foobar</tickerSymbol>
+              <ns0:country/>
+            </ns0:TradePriceRequest>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)
+
+    token = UsernameToken('michael', 'geheim', use_digest=True)
+    envelope, headers = token.sign(envelope, {})
+    expected = """
+        <soap-env:Envelope
+            xmlns:ns0="http://example.com/stockquote.xsd"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <soap-env:Header>
+            <ns0:Security xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+              <ns0:UsernameToken>
+                <ns0:Username>michael</ns0:Username>
+                <ns0:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">hVicspAQSg70JNhe67OHqD9gexc=</ns0:Password>
+                <ns0:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">bW9ja2VkLXJhbmRvbQ==</ns0:Nonce>
+                <ns0:Created xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-05-08T12:00:00+00:00</ns0:Created>
+              </ns0:UsernameToken>
+            </ns0:Security>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:TradePriceRequest>
+              <tickerSymbol>foobar</tickerSymbol>
+              <ns0:country/>
+            </ns0:TradePriceRequest>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """  # noqa
+    assert_nodes_equal(envelope, expected)
+
+
+ at freeze_time('2016-05-08 12:00:00')
+def test_password_digest_custom(monkeypatch):
+    monkeypatch.setattr(os, 'urandom', lambda x: b'mocked-random')
+
+    envelope = load_xml("""
+        <soap-env:Envelope
+            xmlns:ns0="http://example.com/stockquote.xsd"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        >
+          <soap-env:Body>
+            <ns0:TradePriceRequest>
+              <tickerSymbol>foobar</tickerSymbol>
+              <ns0:country/>
+            </ns0:TradePriceRequest>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)
+
+    created = datetime.datetime(2016, 6, 4, 20, 10)
+    token = UsernameToken(
+        'michael', password_digest='12345', use_digest=True,
+        nonce='iets', created=created)
+    envelope, headers = token.sign(envelope, {})
+    expected = """
+        <soap-env:Envelope
+            xmlns:ns0="http://example.com/stockquote.xsd"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <soap-env:Header>
+            <ns0:Security xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+              <ns0:UsernameToken>
+                <ns0:Username>michael</ns0:Username>
+                <ns0:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">12345</ns0:Password>
+                <ns0:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">aWV0cw==</ns0:Nonce>
+                <ns0:Created xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-06-04T20:10:00+00:00</ns0:Created>
+              </ns0:UsernameToken>
+            </ns0:Security>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:TradePriceRequest>
+              <tickerSymbol>foobar</tickerSymbol>
+              <ns0:country/>
+            </ns0:TradePriceRequest>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """  # noqa
+    assert_nodes_equal(envelope, expected)
+
+
+def test_password_prepared():
+    envelope = load_xml("""
+        <soap-env:Envelope
+            xmlns:ns0="http://example.com/stockquote.xsd"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        >
+          <soap-env:Header xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+            <ns0:Security>
+              <ns0:UsernameToken/>
+            </ns0:Security>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:TradePriceRequest>
+              <tickerSymbol>foobar</tickerSymbol>
+              <ns0:country/>
+            </ns0:TradePriceRequest>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """)  # noqa
+
+    token = UsernameToken('michael', 'geheim')
+    envelope, headers = token.sign(envelope, {})
+    expected = """
+        <soap-env:Envelope
+            xmlns:ns0="http://example.com/stockquote.xsd"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <soap-env:Header xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+            <ns0:Security>
+              <ns0:UsernameToken>
+                <ns0:Username>michael</ns0:Username>
+                <ns0:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">geheim</ns0:Password>
+              </ns0:UsernameToken>
+            </ns0:Security>
+          </soap-env:Header>
+          <soap-env:Body>
+            <ns0:TradePriceRequest>
+              <tickerSymbol>foobar</tickerSymbol>
+              <ns0:country/>
+            </ns0:TradePriceRequest>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """  # noqa
+    assert_nodes_equal(envelope, expected)
diff --git a/tests/test_wsse_utils.py b/tests/test_wsse_utils.py
new file mode 100644
index 0000000..8b3a3aa
--- /dev/null
+++ b/tests/test_wsse_utils.py
@@ -0,0 +1,25 @@
+from lxml import etree
+
+from zeep.wsse import utils
+
+
+def test_get_security_header():
+    doc = etree.fromstring("""
+        <soap-env:Envelope
+            xmlns:ns0="http://example.com/stockquote.xsd"
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        >
+          <soap-env:Body>
+            <ns0:TradePriceRequest>
+              <tickerSymbol>foobar</tickerSymbol>
+              <ns0:country/>
+            </ns0:TradePriceRequest>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """.strip())
+
+    element = utils.get_security_header(doc)
+    assert element.tag == '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security'  # noqa
diff --git a/tests/test_xsd_any.py b/tests/test_xsd_any.py
new file mode 100644
index 0000000..4137b34
--- /dev/null
+++ b/tests/test_xsd_any.py
@@ -0,0 +1,280 @@
+import datetime
+
+import pytest
+from lxml import etree
+
+from tests.utils import assert_nodes_equal, load_xml
+from zeep import xsd
+
+
+def get_any_schema():
+    return xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="item" type="string"/>
+          <element name="container">
+            <complexType>
+              <sequence>
+                <any/>
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+
+def test_any_simple():
+    schema = get_any_schema()
+
+    item_elm = schema.get_element('{http://tests.python-zeep.org/}item')
+    assert isinstance(item_elm.type, xsd.String)
+
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+
+    # Create via arg
+    obj = container_elm(xsd.AnyObject(item_elm, item_elm('argh')))
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    expected = """
+        <document>
+            <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:item>argh</ns0:item>
+            </ns0:container>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    item = container_elm.parse(node.getchildren()[0], schema)
+    assert item._value_1 == 'argh'
+
+    # Create via kwarg _value_1
+    obj = container_elm(_value_1=xsd.AnyObject(item_elm, item_elm('argh')))
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    expected = """
+        <document>
+            <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:item>argh</ns0:item>
+            </ns0:container>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    item = container_elm.parse(node.getchildren()[0], schema)
+    assert item._value_1 == 'argh'
+
+
+def test_any_value_element_tree():
+    schema = get_any_schema()
+
+    item = etree.Element('{http://tests.python-zeep.org}lxml')
+    etree.SubElement(item, 'node').text = 'foo'
+
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+
+    # Create via arg
+    obj = container_elm(item)
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    expected = """
+        <document>
+            <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:lxml xmlns:ns0="http://tests.python-zeep.org">
+                    <node>foo</node>
+                </ns0:lxml>
+            </ns0:container>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    item = container_elm.parse(node.getchildren()[0], schema)
+    assert isinstance(item._value_1, etree._Element)
+    assert item._value_1.tag == '{http://tests.python-zeep.org}lxml'
+
+
+def test_any_value_invalid():
+    schema = get_any_schema()
+
+    class SomeThing(object):
+        pass
+
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+
+    # Create via arg
+    item = SomeThing()
+    obj = container_elm(item)
+    node = etree.Element('document')
+
+    with pytest.raises(TypeError):
+        container_elm.render(node, obj)
+
+
+def test_any_with_ref():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                   elementFormDefault="qualified">
+          <element name="item" type="string"/>
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element ref="tns:item"/>
+                <any/>
+                <any maxOccurs="unbounded"/>
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+    item_elm = schema.get_element('{http://tests.python-zeep.org/}item')
+    assert isinstance(item_elm.type, xsd.String)
+
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+    obj = container_elm(
+        item='bar',
+        _value_1=xsd.AnyObject(item_elm, item_elm('argh')))
+
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    expected = """
+        <document>
+            <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:item>bar</ns0:item>
+                <ns0:item>argh</ns0:item>
+            </ns0:container>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    item = container_elm.parse(node.getchildren()[0], schema)
+    assert item.item == 'bar'
+    assert item._value_1 == 'argh'
+
+
+def test_element_any_parse():
+    node = load_xml("""
+        <xsd:schema
+            elementFormDefault="qualified"
+            targetNamespace="https://tests.python-zeep.org"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:any/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+
+    schema = xsd.Schema(node)
+
+    node = load_xml("""
+          <container xmlns="https://tests.python-zeep.org">
+            <something>
+              <contains>text</contains>
+            </something>
+          </container>
+    """)
+
+    elm = schema.get_element('ns0:container')
+    elm.parse(node, schema)
+
+
+def test_element_any_type():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element name="something" type="anyType"/>
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """.strip())
+    schema = xsd.Schema(node)
+
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+    obj = container_elm(something='bar')
+
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    expected = """
+        <document>
+            <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:something>bar</ns0:something>
+            </ns0:container>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    item = container_elm.parse(node.getchildren()[0], schema)
+    assert item.something == 'bar'
+
+
+def test_any_in_nested_sequence():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:tns="http://tests.python-zeep.org/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            elementFormDefault="qualified"
+            targetNamespace="http://tests.python-zeep.org/"
+        >
+          <xsd:element name="something" type="xsd:date"/>
+          <xsd:element name="foobar" type="xsd:boolean"/>
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="items" minOccurs="0">
+                  <xsd:complexType>
+                    <xsd:sequence>
+                      <xsd:any namespace="##any" processContents="lax"/>
+                    </xsd:sequence>
+                  </xsd:complexType>
+                </xsd:element>
+                <xsd:element name="version" type="xsd:string"/>
+                <xsd:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """))   # noqa
+
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+    assert container_elm.signature() == (
+        'items: {_value_1: ANY}, version: xsd:string, _value_1: ANY[]')
+
+    something = schema.get_element('{http://tests.python-zeep.org/}something')
+    foobar = schema.get_element('{http://tests.python-zeep.org/}foobar')
+
+    any_1 = xsd.AnyObject(something, datetime.date(2016, 7, 4))
+    any_2 = xsd.AnyObject(foobar, True)
+    obj = container_elm(
+        items={'_value_1': any_1}, version='str1234', _value_1=[any_1, any_2])
+
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    expected = """
+        <document>
+          <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+            <ns0:items>
+              <ns0:something>2016-07-04</ns0:something>
+            </ns0:items>
+            <ns0:version>str1234</ns0:version>
+            <ns0:something>2016-07-04</ns0:something>
+            <ns0:foobar>true</ns0:foobar>
+          </ns0:container>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    item = container_elm.parse(node.getchildren()[0], schema)
+    assert item.items._value_1 == datetime.date(2016, 7, 4)
+    assert item.version == 'str1234'
+    assert item._value_1 == [datetime.date(2016, 7, 4), True]
diff --git a/tests/test_xsd_attributes.py b/tests/test_xsd_attributes.py
new file mode 100644
index 0000000..3e42458
--- /dev/null
+++ b/tests/test_xsd_attributes.py
@@ -0,0 +1,420 @@
+from collections import OrderedDict
+
+from lxml import etree
+
+from tests.utils import assert_nodes_equal, load_xml
+from zeep import xsd
+
+
+def test_anyattribute():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element name="foo" type="xsd:string" />
+              </sequence>
+              <xsd:anyAttribute processContents="lax"/>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+    assert container_elm.signature() == (
+        'foo: xsd:string, _attr_1: {}')
+    obj = container_elm(foo='bar', _attr_1=OrderedDict([
+        ('hiep', 'hoi'), ('hoi', 'hiep')
+    ]))
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/" hiep="hoi" hoi="hiep">
+          <ns0:foo>bar</ns0:foo>
+        </ns0:container>
+      </document>
+    """
+
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    assert_nodes_equal(expected, node)
+
+    item = container_elm.parse(node.getchildren()[0], schema)
+    assert item._attr_1 == {'hiep': 'hoi', 'hoi': 'hiep'}
+    assert item.foo == 'bar'
+
+
+def test_attribute_list_type():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <simpleType name="list">
+            <list itemType="int"/>
+          </simpleType>
+
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element name="foo" type="xsd:string" />
+              </sequence>
+              <xsd:attribute name="lijst" type="tns:list"/>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+    assert container_elm.signature() == ('foo: xsd:string, lijst: xsd:int[]')
+    obj = container_elm(foo='bar', lijst=[1, 2, 3])
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/" lijst="1 2 3">
+          <ns0:foo>bar</ns0:foo>
+        </ns0:container>
+      </document>
+    """
+
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    assert_nodes_equal(expected, node)
+
+    item = container_elm.parse(node.getchildren()[0], schema)
+    assert item.lijst == [1, 2, 3]
+    assert item.foo == 'bar'
+
+
+def test_ref_attribute_qualified():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                attributeFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:attribute ref="tns:attr" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:attribute name="attr" type="xsd:string" />
+        </xsd:schema>
+    """))
+
+    elm_cls = schema.get_element('{http://tests.python-zeep.org/}container')
+    instance = elm_cls(attr="hoi")
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/" ns0:attr="hoi"/>
+      </document>
+    """
+
+    node = etree.Element('document')
+    elm_cls.render(node, instance)
+    assert_nodes_equal(expected, node)
+
+
+def test_ref_attribute_unqualified():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                attributeFormDefault="unqualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:attribute ref="tns:attr" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:attribute name="attr" type="xsd:string" />
+        </xsd:schema>
+    """))
+
+    elm_cls = schema.get_element('{http://tests.python-zeep.org/}container')
+    instance = elm_cls(attr="hoi")
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/" ns0:attr="hoi"/>
+      </document>
+    """
+
+    node = etree.Element('document')
+    elm_cls.render(node, instance)
+    assert_nodes_equal(expected, node)
+
+
+def test_complex_type_with_attributes():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+          <xs:complexType name="Address">
+            <xs:sequence>
+              <xs:element minOccurs="0" maxOccurs="1" name="NameFirst" type="xs:string"/>
+              <xs:element minOccurs="0" maxOccurs="1" name="NameLast" type="xs:string"/>
+              <xs:element minOccurs="0" maxOccurs="1" name="Email" type="xs:string"/>
+            </xs:sequence>
+            <xs:attribute name="id" type="xs:string" use="required"/>
+          </xs:complexType>
+          <xs:element name="Address" type="Address"/>
+        </xs:schema>
+    """))
+
+    address_type = schema.get_element('Address')
+    obj = address_type(
+        NameFirst='John', NameLast='Doe', Email='j.doe at example.com', id='123')
+
+    node = etree.Element('document')
+    address_type.render(node, obj)
+
+    expected = """
+        <document>
+            <Address id="123">
+                <NameFirst>John</NameFirst>
+                <NameLast>Doe</NameLast>
+                <Email>j.doe at example.com</Email>
+            </Address>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_qualified_attribute():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                attributeFormDefault="qualified"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="Address">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="foo" type="xsd:string" form="unqualified" />
+              </xsd:sequence>
+              <xsd:attribute name="id" type="xsd:string" use="required" form="unqualified" />
+              <xsd:attribute name="pos" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """))
+
+    address_type = schema.get_element('{http://tests.python-zeep.org/}Address')
+    obj = address_type(foo='bar', id="20", pos="30")
+
+    expected = """
+      <document>
+        <ns0:Address xmlns:ns0="http://tests.python-zeep.org/" id="20" ns0:pos="30">
+          <foo>bar</foo>
+        </ns0:Address>
+      </document>
+    """
+
+    node = etree.Element('document')
+    address_type.render(node, obj)
+    assert_nodes_equal(expected, node)
+
+
+def test_group():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                attributeFormDefault="qualified"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+
+          <xsd:attributeGroup name="groepje">
+            <xsd:attribute name="id" type="xsd:string" use="required" form="unqualified" />
+            <xsd:attribute name="pos" type="xsd:string" use="required" />
+          </xsd:attributeGroup>
+          <xsd:element name="Address">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="foo" type="xsd:string" form="unqualified" />
+              </xsd:sequence>
+              <xsd:attributeGroup ref="tns:groepje"/>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """))
+
+    address_type = schema.get_element('{http://tests.python-zeep.org/}Address')
+    obj = address_type(foo='bar', id="20", pos="30")
+
+    expected = """
+      <document>
+        <ns0:Address xmlns:ns0="http://tests.python-zeep.org/" id="20" ns0:pos="30">
+          <foo>bar</foo>
+        </ns0:Address>
+      </document>
+    """
+
+    node = etree.Element('document')
+    address_type.render(node, obj)
+    assert_nodes_equal(expected, node)
+
+
+def test_group_nested():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                attributeFormDefault="qualified"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+
+          <xsd:attributeGroup name="groepje">
+            <xsd:attribute name="id" type="xsd:string" use="required" form="unqualified" />
+            <xsd:attribute name="pos" type="xsd:string" use="required" />
+            <xsd:attributeGroup ref="tns:nestje"/>
+          </xsd:attributeGroup>
+
+          <xsd:attributeGroup name="nestje">
+            <xsd:attribute name="size" type="xsd:string" use="required" />
+          </xsd:attributeGroup>
+
+          <xsd:element name="Address">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="foo" type="xsd:string" form="unqualified" />
+              </xsd:sequence>
+              <xsd:attributeGroup ref="tns:groepje"/>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """))
+
+    address_type = schema.get_element('{http://tests.python-zeep.org/}Address')
+    obj = address_type(foo='bar', id="20", pos="30", size="maat")
+
+    expected = """
+      <document>
+        <ns0:Address
+            xmlns:ns0="http://tests.python-zeep.org/" id="20" ns0:pos="30" ns0:size="maat">
+          <foo>bar</foo>
+        </ns0:Address>
+      </document>
+    """
+
+    node = etree.Element('document')
+    address_type.render(node, obj)
+    assert_nodes_equal(expected, node)
+
+
+def test_nested_attribute():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element name="item">
+                    <complexType>
+                        <sequence>
+                            <element name="x" type="xsd:string"/>
+                        </sequence>
+                        <attribute name="y" type="xsd:string"/>
+                    </complexType>
+                </element>
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+    assert container_elm.signature() == 'item: {x: xsd:string, y: xsd:string}'
+    obj = container_elm(item={'x': 'foo', 'y': 'bar'})
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item y="bar">
+            <ns0:x>foo</ns0:x>
+          </ns0:item>
+        </ns0:container>
+      </document>
+    """
+
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    assert_nodes_equal(expected, node)
+
+
+def test_attribute_union_type():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <simpleType name="one">
+            <restriction base="xsd:string"/>
+          </simpleType>
+          <simpleType name="parent">
+            <union memberTypes="one two"/>
+          </simpleType>
+          <simpleType name="two">
+            <restriction base="xsd:string"/>
+          </simpleType>
+          <attribute name="something" type="tns:something"/>
+          <simpleType name="something">
+            <restriction base="tns:parent">
+              <enumeration value="preserve"/>
+            </restriction>
+          </simpleType>
+        </schema>
+    """))
+
+    attr = schema.get_attribute('{http://tests.python-zeep.org/}something')
+    assert attr('foo') == 'foo'
+
+
+def test_attribute_union_type_inline():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <simpleType name="parent">
+            <union>
+              <simpleType name="one">
+                <restriction base="xsd:string"/>
+              </simpleType>
+              <simpleType name="two">
+                <restriction base="xsd:string"/>
+              </simpleType>
+            </union>
+          </simpleType>
+          <attribute name="something" type="tns:something"/>
+          <simpleType name="something">
+            <restriction base="tns:parent">
+              <enumeration value="preserve"/>
+            </restriction>
+          </simpleType>
+        </schema>
+    """))
+
+    attr = schema.get_attribute('{http://tests.python-zeep.org/}something')
+    assert attr('foo') == 'foo'
diff --git a/tests/test_xsd_builtins.py b/tests/test_xsd_builtins.py
index 0d3da42..a10951d 100644
--- a/tests/test_xsd_builtins.py
+++ b/tests/test_xsd_builtins.py
@@ -122,6 +122,10 @@ class TestDateTime:
         value = datetime.datetime(2016, 3, 4, 21, 14, 42, tzinfo=pytz.utc)
         assert instance.xmlvalue(value) == '2016-03-04T21:14:42Z'
 
+        value = datetime.datetime(2016, 3, 4, 21, 14, 42, 123456, tzinfo=pytz.utc)
+        assert instance.xmlvalue(value) == '2016-03-04T21:14:42.123456Z'
+
+        value = datetime.datetime(2016, 3, 4, 21, 14, 42, tzinfo=pytz.utc)
         value = value.astimezone(pytz.timezone('Europe/Amsterdam'))
         assert instance.xmlvalue(value) == '2016-03-04T22:14:42+01:00'
 
@@ -130,6 +134,9 @@ class TestDateTime:
         value = datetime.datetime(2016, 3, 4, 21, 14, 42)
         assert instance.pythonvalue('2016-03-04T21:14:42') == value
 
+        value = datetime.datetime(2016, 3, 4, 21, 14, 42, 123456)
+        assert instance.pythonvalue('2016-03-04T21:14:42.123456') == value
+
     def test_pythonvalue_invalid(self):
         instance = builtins.DateTime()
         with pytest.raises(ValueError):
diff --git a/tests/test_xsd_choice.py b/tests/test_xsd_choice.py
new file mode 100644
index 0000000..7478962
--- /dev/null
+++ b/tests/test_xsd_choice.py
@@ -0,0 +1,979 @@
+import pytest
+from lxml import etree
+
+from tests.utils import assert_nodes_equal, load_xml, render_node
+from zeep import xsd
+from zeep.exceptions import XMLParseError
+from zeep.helpers import serialize_object
+
+
+def test_choice_element():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:choice>
+                <xsd:element name="item_1" type="xsd:string" />
+                <xsd:element name="item_2" type="xsd:string" />
+                <xsd:element name="item_3" type="xsd:string" />
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """.strip())
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+
+    value = element(item_1="foo")
+    assert value.item_1 == 'foo'
+    assert value.item_2 is None
+    assert value.item_3 is None
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>foo</ns0:item_1>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+    value = element.parse(node.getchildren()[0], schema)
+    assert value.item_1 == 'foo'
+    assert value.item_2 is None
+    assert value.item_3 is None
+
+
+def test_choice_element_second_elm():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:choice>
+                <xsd:element name="item_1" type="xsd:string" />
+                <xsd:element name="item_2" type="xsd:string" />
+                <xsd:element name="item_3" type="xsd:string" />
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """.strip())
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+
+    value = element(item_2="foo")
+    assert value.item_1 is None
+    assert value.item_2 == 'foo'
+    assert value.item_3 is None
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_2>foo</ns0:item_2>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+    value = element.parse(node.getchildren()[0], schema)
+    assert value.item_1 is None
+    assert value.item_2 == 'foo'
+    assert value.item_3 is None
+
+
+def test_choice_element_multiple():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:choice maxOccurs="3">
+                <xsd:element name="item_1" type="xsd:string" />
+                <xsd:element name="item_2" type="xsd:string" />
+                <xsd:element name="item_3" type="xsd:string" />
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """.strip())
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+
+    value = element(_value_1=[
+        {'item_1': 'foo'}, {'item_2': 'bar'}, {'item_1': 'three'},
+    ])
+    assert value._value_1 == [
+        {'item_1': 'foo'}, {'item_2': 'bar'}, {'item_1': 'three'},
+    ]
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>foo</ns0:item_1>
+          <ns0:item_2>bar</ns0:item_2>
+          <ns0:item_1>three</ns0:item_1>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+    value = element.parse(node.getchildren()[0], schema)
+    assert value._value_1 == [
+        {'item_1': 'foo'}, {'item_2': 'bar'}, {'item_1': 'three'},
+    ]
+
+
+def test_choice_element_optional():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:choice minOccurs="0">
+                  <xsd:element name="item_1" type="xsd:string" />
+                  <xsd:element name="item_2" type="xsd:string" />
+                  <xsd:element name="item_3" type="xsd:string" />
+                </xsd:choice>
+                <xsd:element name="item_4" type="xsd:string" />
+             </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """.strip())
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    value = element(item_4="foo")
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_4>foo</ns0:item_4>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+
+def test_choice_element_with_any():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:choice minOccurs="0">
+                <xsd:element name="item_1" type="xsd:string" />
+                <xsd:element name="item_2" type="xsd:string" />
+                <xsd:element name="item_3" type="xsd:string" />
+                <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+              </xsd:choice>
+              <xsd:attribute name="name" type="xsd:QName" use="required" />
+              <xsd:attribute name="something" type="xsd:boolean" use="required" />
+              <xsd:anyAttribute namespace="##other" processContents="lax"/>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """.strip())
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    value = element(item_1="foo", name="foo", something="bar")
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/" name="foo" something="true">
+          <ns0:item_1>foo</ns0:item_1>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+    result = element.parse(node.getchildren()[0], schema)
+    assert result.name == 'foo'
+    assert result.something is True
+    assert result.item_1 == 'foo'
+
+
+def test_choice_element_with_any_max_occurs():
+    schema = xsd.Schema(load_xml("""
+        <schema targetNamespace="http://tests.python-zeep.org/"
+            xmlns="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+
+          <element name="item_any" type="string"/>
+          <element name="container">
+            <complexType>
+                <sequence>
+                  <choice minOccurs="0">
+                    <element maxOccurs="999" minOccurs="0" name="item_1" type="string"/>
+                    <sequence>
+                      <element minOccurs="0" name="item_2"/>
+                      <any maxOccurs="unbounded" minOccurs="0"/>
+                    </sequence>
+                  </choice>
+                </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+    element = schema.get_element('ns0:container')
+    value = element(
+        item_2="item-2",
+        _value_1=[
+            xsd.AnyObject(schema.get_element('ns0:item_any'), 'any-content')
+        ])
+
+    expected = """
+        <document>
+          <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+            <ns0:item_2>item-2</ns0:item_2>
+            <ns0:item_any>any-content</ns0:item_any>
+          </ns0:container>
+        </document>
+    """
+    node = render_node(element, value)
+    assert_nodes_equal(node, expected)
+    result = element.parse(node.getchildren()[0], schema)
+    assert result.item_2 == 'item-2'
+    assert result._value_1 == ['any-content']
+
+
+def test_choice_optional_values():
+    schema = load_xml("""
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+          <xsd:complexType name="Transport">
+            <xsd:sequence>
+                <xsd:choice minOccurs="0" maxOccurs="1">
+                    <xsd:element name="item" type="xsd:string"/>
+                </xsd:choice>
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(schema)
+
+    node = load_xml("<Transport></Transport>")
+    elm = schema.get_type('ns0:Transport')
+    elm.parse_xmlelement(node, schema)
+
+
+def test_choice_in_sequence():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="something" type="xsd:string" />
+                <xsd:choice>
+                  <xsd:element name="item_1" type="xsd:string" />
+                  <xsd:element name="item_2" type="xsd:string" />
+                  <xsd:element name="item_3" type="xsd:string" />
+                </xsd:choice>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """.strip())
+    schema = xsd.Schema(node)
+    container_elm = schema.get_element('ns0:container')
+
+    assert container_elm.type.signature() == (
+        'something: xsd:string, ({item_1: xsd:string} | {item_2: xsd:string} | {item_3: xsd:string})')  # noqa
+    value = container_elm(item_1='item-1')
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:something/>
+          <ns0:item_1>item-1</ns0:item_1>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    container_elm.render(node, value)
+    assert_nodes_equal(expected, node)
+
+
+def test_choice_with_sequence():
+    node = load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:choice>
+                <xsd:sequence>
+                    <xsd:element name="item_1" type="xsd:string"/>
+                    <xsd:element name="item_2" type="xsd:string"/>
+                </xsd:sequence>
+                <xsd:sequence>
+                    <xsd:element name="item_3" type="xsd:string"/>
+                    <xsd:element name="item_4" type="xsd:string"/>
+                </xsd:sequence>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    assert element.type.signature() == (
+        '({item_1: xsd:string, item_2: xsd:string} | {item_3: xsd:string, item_4: xsd:string})')
+    value = element(item_1='foo', item_2='bar')
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>foo</ns0:item_1>
+          <ns0:item_2>bar</ns0:item_2>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+
+def test_choice_with_sequence_once():
+    node = load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:sequence>
+                <xsd:element name="item_0" type="xsd:string"/>
+                <xsd:choice>
+                  <xsd:sequence>
+                      <xsd:element name="item_1" type="xsd:string"/>
+                      <xsd:element name="item_2" type="xsd:string"/>
+                  </xsd:sequence>
+                </xsd:choice>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    assert element.type.signature() == (
+        'item_0: xsd:string, ({item_1: xsd:string, item_2: xsd:string})')
+    value = element(item_0='nul', item_1='foo', item_2='bar')
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_0>nul</ns0:item_0>
+          <ns0:item_1>foo</ns0:item_1>
+          <ns0:item_2>bar</ns0:item_2>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+
+def test_choice_with_sequence_once_extra_data():
+    node = load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:sequence>
+                <xsd:element name="item_0" type="xsd:string"/>
+                <xsd:choice>
+                  <xsd:sequence>
+                      <xsd:element name="item_1" type="xsd:string"/>
+                      <xsd:element name="item_2" type="xsd:string"/>
+                  </xsd:sequence>
+                </xsd:choice>
+                <xsd:element name="item_3" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    assert element.type.signature() == (
+        'item_0: xsd:string, ({item_1: xsd:string, item_2: xsd:string}), item_3: xsd:string')
+    value = element(item_0='nul', item_1='foo', item_2='bar', item_3='item-3')
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_0>nul</ns0:item_0>
+          <ns0:item_1>foo</ns0:item_1>
+          <ns0:item_2>bar</ns0:item_2>
+          <ns0:item_3>item-3</ns0:item_3>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+
+def test_choice_with_sequence_second():
+    node = load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:choice>
+                <xsd:sequence>
+                    <xsd:element name="item_1" type="xsd:string"/>
+                    <xsd:element name="item_2" type="xsd:string"/>
+                </xsd:sequence>
+                <xsd:sequence>
+                    <xsd:element name="item_3" type="xsd:string"/>
+                    <xsd:element name="item_4" type="xsd:string"/>
+                </xsd:sequence>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    assert element.type.signature() == (
+        '({item_1: xsd:string, item_2: xsd:string} | {item_3: xsd:string, item_4: xsd:string})')
+    value = element(item_3='foo', item_4='bar')
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_3>foo</ns0:item_3>
+          <ns0:item_4>bar</ns0:item_4>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+
+def test_choice_with_sequence_invalid():
+    node = load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:choice>
+                <xsd:sequence>
+                    <xsd:element name="item_1" type="xsd:string"/>
+                    <xsd:element name="item_2" type="xsd:string"/>
+                </xsd:sequence>
+                <xsd:sequence>
+                    <xsd:element name="item_3" type="xsd:string"/>
+                    <xsd:element name="item_4" type="xsd:string"/>
+                </xsd:sequence>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    assert element.type.signature() == (
+        '({item_1: xsd:string, item_2: xsd:string} | {item_3: xsd:string, item_4: xsd:string})')
+
+    with pytest.raises(TypeError):
+        element(item_1='foo', item_4='bar')
+
+
+def test_choice_with_sequence_change():
+    node = load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name='ElementName'>
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:choice>
+                <xsd:sequence>
+                    <xsd:element name="item_1" type="xsd:string"/>
+                    <xsd:element name="item_2" type="xsd:string"/>
+                </xsd:sequence>
+                <xsd:sequence>
+                    <xsd:element name="item_3" type="xsd:string"/>
+                    <xsd:element name="item_4" type="xsd:string"/>
+                </xsd:sequence>
+                <xsd:element name="nee" type="xsd:string"/>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:ElementName')
+
+    elm = element(item_1='foo', item_2='bar')
+    assert serialize_object(elm) == {
+        'item_3': None,
+        'item_2': 'bar',
+        'item_1': 'foo',
+        'item_4': None,
+        'nee': None
+    }
+
+    elm.item_1 = 'bla-1'
+    elm.item_2 = 'bla-2'
+
+    expected = """
+      <document>
+        <ns0:ElementName xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>bla-1</ns0:item_1>
+          <ns0:item_2>bla-2</ns0:item_2>
+        </ns0:ElementName>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, elm)
+    assert_nodes_equal(expected, node)
+
+
+def test_choice_with_sequence_change_named():
+    node = load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name='ElementName'>
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:choice>
+                <xsd:sequence>
+                    <xsd:element name="item_1" type="xsd:string"/>
+                    <xsd:element name="item_2" type="xsd:string"/>
+                </xsd:sequence>
+                <xsd:element name="item_3" type="xsd:string"/>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:ElementName')
+    elm = element(item_3='foo')
+    elm = element(item_1='foo', item_2='bar')
+    assert elm['item_1'] == 'foo'
+    assert elm['item_2'] == 'bar'
+
+    elm['item_1'] = 'bla-1'
+    elm['item_2'] = 'bla-2'
+
+    expected = """
+      <document>
+        <ns0:ElementName xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>bla-1</ns0:item_1>
+          <ns0:item_2>bla-2</ns0:item_2>
+        </ns0:ElementName>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, elm)
+    assert_nodes_equal(expected, node)
+
+
+def test_choice_with_sequence_multiple():
+    node = load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:choice maxOccurs="2">
+                <xsd:sequence>
+                    <xsd:element name="item_1" type="xsd:string"/>
+                    <xsd:element name="item_2" type="xsd:string"/>
+                </xsd:sequence>
+                <xsd:sequence>
+                    <xsd:element name="item_3" type="xsd:string"/>
+                    <xsd:element name="item_4" type="xsd:string"/>
+                </xsd:sequence>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    assert element.type.signature() == (
+        '({item_1: xsd:string, item_2: xsd:string} | {item_3: xsd:string, item_4: xsd:string})[]')
+    value = element(_value_1=[
+        dict(item_1='foo', item_2='bar'),
+        dict(item_3='foo', item_4='bar'),
+    ])
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>foo</ns0:item_1>
+          <ns0:item_2>bar</ns0:item_2>
+          <ns0:item_3>foo</ns0:item_3>
+          <ns0:item_4>bar</ns0:item_4>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+
+def test_choice_with_sequence_and_element():
+    node = load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:choice>
+                <xsd:element name="item_1" type="xsd:string"/>
+                <xsd:sequence>
+                  <xsd:choice>
+                    <xsd:element name="item_2" type="xsd:string"/>
+                    <xsd:element name="item_3" type="xsd:string"/>
+                  </xsd:choice>
+                </xsd:sequence>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    assert element.type.signature() == (
+        '({item_1: xsd:string} | {({item_2: xsd:string} | {item_3: xsd:string})})')
+
+    value = element(item_2='foo')
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_2>foo</ns0:item_2>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+
+def test_element_ref_in_choice():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                   elementFormDefault="qualified">
+          <element name="foo" type="string"/>
+          <element name="bar" type="string"/>
+          <element name="container">
+            <complexType>
+              <sequence>
+                <choice>
+                  <element ref="tns:foo"/>
+                  <element ref="tns:bar"/>
+                </choice>
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """.strip())
+
+    schema = xsd.Schema(node)
+
+    foo_type = schema.get_element('{http://tests.python-zeep.org/}foo')
+    assert isinstance(foo_type.type, xsd.String)
+
+    custom_type = schema.get_element('{http://tests.python-zeep.org/}container')
+
+    value = custom_type(foo='bar')
+    assert value.foo == 'bar'
+    assert value.bar is None
+
+    node = etree.Element('document')
+    custom_type.render(node, value)
+    expected = """
+        <document>
+            <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:foo>bar</ns0:foo>
+            </ns0:container>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_parse_dont_loop():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:choice maxOccurs="unbounded">
+                <xsd:element name="item_1" type="xsd:string"/>
+                <xsd:element name="item_2" type="xsd:string"/>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """))
+
+    element = schema.get_element('ns0:container')
+    expected = load_xml("""
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>foo</ns0:item_1>
+          <ns0:item_2>bar</ns0:item_2>
+          <ns0:item_3>foo</ns0:item_3>
+          <ns0:item_4>bar</ns0:item_4>
+        </ns0:container>
+    """)
+    with pytest.raises(XMLParseError):
+        element.parse(expected, schema)
+
+
+def test_parse_check_unexpected():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:choice maxOccurs="unbounded">
+                <xsd:element name="item_1" type="xsd:string"/>
+                <xsd:element name="item_2" type="xsd:string"/>
+              </xsd:choice>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """))
+
+    element = schema.get_element('ns0:container')
+    expected = load_xml("""
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>foo</ns0:item_1>
+          <ns0:item_2>bar</ns0:item_2>
+          <ns0:item_3>foo</ns0:item_3>
+        </ns0:container>
+    """)
+    with pytest.raises(XMLParseError):
+        element.parse(expected, schema)
+
+
+def test_parse_check_mixed():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="container">
+            <xsd:complexType xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+              <xsd:sequence>
+                <xsd:choice maxOccurs="unbounded">
+                  <xsd:element name="item_1" type="xsd:string"/>
+                  <xsd:element name="item_2" type="xsd:string"/>
+                </xsd:choice>
+                <xsd:element name="item_3" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """))
+
+    element = schema.get_element('ns0:container')
+    expected = load_xml("""
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>foo</ns0:item_1>
+          <ns0:item_2>bar</ns0:item_2>
+          <ns0:item_3>foo</ns0:item_3>
+        </ns0:container>
+    """)
+    element.parse(expected, schema)
+
+
+def test_parse_check_mixed_choices():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema
+                xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <element name="container">
+            <complexType>
+              <sequence>
+                <choice>
+                  <choice>
+                    <element name="item_1_1" type="string"/>
+                    <sequence>
+                      <element name="item_1_2a" type="string"/>
+                      <element name="item_1_2b" type="string" minOccurs="0"/>
+                    </sequence>
+                  </choice>
+                  <element name="item_2" type="string"/>
+                  <element name="item_3" type="string"/>
+                </choice>
+                <element name="isRegistered" type="boolean" fixed="true" minOccurs="0"/>
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+    element = schema.get_element('ns0:container')
+
+    # item_1_1
+    value = element(item_1_1="foo")
+    assert value.item_1_1 == 'foo'
+
+    node = etree.Element('document')
+    element.render(node, value)
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1_1>foo</ns0:item_1_1>
+        </ns0:container>
+      </document>
+    """
+    assert_nodes_equal(expected, node)
+
+    # item_1_2a
+    value = element(item_1_2a="foo")
+    node = etree.Element('document')
+    element.render(node, value)
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1_2a>foo</ns0:item_1_2a>
+        </ns0:container>
+      </document>
+    """
+    assert_nodes_equal(expected, node)
+
+    # item_1_2a & item_1_2b
+    value = element(item_1_2a="foo", item_1_2b="bar")
+    node = etree.Element('document')
+    element.render(node, value)
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1_2a>foo</ns0:item_1_2a>
+          <ns0:item_1_2b>bar</ns0:item_1_2b>
+        </ns0:container>
+      </document>
+    """
+    assert_nodes_equal(expected, node)
+
+    # item_2
+    value = element(item_2="foo")
+    assert value.item_2 == 'foo'
+    node = etree.Element('document')
+    element.render(node, value)
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_2>foo</ns0:item_2>
+        </ns0:container>
+      </document>
+    """
+    assert_nodes_equal(expected, node)
+
+    # item_3
+    value = element(item_3="foo")
+    assert value.item_3 == 'foo'
+    node = etree.Element('document')
+    element.render(node, value)
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_3>foo</ns0:item_3>
+        </ns0:container>
+      </document>
+    """
+    assert_nodes_equal(expected, node)
diff --git a/tests/test_xsd_complex_types.py b/tests/test_xsd_complex_types.py
new file mode 100644
index 0000000..cdfbde3
--- /dev/null
+++ b/tests/test_xsd_complex_types.py
@@ -0,0 +1,233 @@
+import pytest
+
+from lxml import etree
+from tests.utils import assert_nodes_equal, load_xml, render_node
+from zeep import xsd
+
+
+def test_single_node():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element minOccurs="0" maxOccurs="1" name="item" type="string" />
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+    schema.set_ns_prefix('tns', 'http://tests.python-zeep.org/')
+
+    container_elm = schema.get_element('tns:container')
+    obj = container_elm(item='bar')
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item>bar</ns0:item>
+        </ns0:container>
+      </document>
+    """
+    result = render_node(container_elm, obj)
+    assert_nodes_equal(result, expected)
+
+    obj = container_elm.parse(result[0], schema)
+    assert obj.item == 'bar'
+
+
+def test_nested_sequence():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element minOccurs="0" maxOccurs="1" name="item">
+                  <complexType>
+                    <sequence>
+                      <element name="x" type="integer"/>
+                      <element name="y" type="integer"/>
+                    </sequence>
+                  </complexType>
+                </element>
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+    schema.set_ns_prefix('tns', 'http://tests.python-zeep.org/')
+
+    container_elm = schema.get_element('tns:container')
+    obj = container_elm(item={'x': 1, 'y': 2})
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item>
+            <ns0:x>1</ns0:x>
+            <ns0:y>2</ns0:y>
+          </ns0:item>
+        </ns0:container>
+      </document>
+    """
+    result = render_node(container_elm, obj)
+    assert_nodes_equal(result, expected)
+
+    obj = container_elm.parse(result[0], schema)
+    assert obj.item.x == 1
+    assert obj.item.y == 2
+
+
+def test_single_node_array():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element minOccurs="0" maxOccurs="unbounded" name="item" type="string" />
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+    schema.set_ns_prefix('tns', 'http://tests.python-zeep.org/')
+
+    container_elm = schema.get_element('tns:container')
+    obj = container_elm(item=['item-1', 'item-2', 'item-3'])
+    assert obj.item == ['item-1', 'item-2', 'item-3']
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item>item-1</ns0:item>
+          <ns0:item>item-2</ns0:item>
+          <ns0:item>item-3</ns0:item>
+        </ns0:container>
+      </document>
+    """
+    result = render_node(container_elm, obj)
+    assert_nodes_equal(result, expected)
+
+    obj = container_elm.parse(result[0], schema)
+    assert obj.item == ['item-1', 'item-2', 'item-3']
+
+
+def test_single_node_no_iterable():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element minOccurs="0" maxOccurs="1" name="item" type="string" />
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+    schema.set_ns_prefix('tns', 'http://tests.python-zeep.org/')
+
+    container_elm = schema.get_element('tns:container')
+
+    obj = container_elm(item=['item-1', 'item-2', 'item-3'])
+    assert obj.item == ['item-1', 'item-2', 'item-3']
+
+    with pytest.raises(ValueError):
+        render_node(container_elm, obj)
+
+
+def test_complex_any_types():
+    # see https://github.com/mvantellingen/python-zeep/issues/252
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="container">
+            <complexType>
+              <sequence>
+                <element minOccurs="0" maxOccurs="1" name="auth" type="anyType" />
+                <element minOccurs="0" maxOccurs="1" name="params" type="anyType" />
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+    schema.set_ns_prefix('tns', 'http://tests.python-zeep.org/')
+    KeyValueData = xsd.Element(
+        '{http://xml.apache.org/xml-soap}KeyValueData',
+        xsd.ComplexType(
+            xsd.Sequence([
+                xsd.Element(
+                    'key',
+                    xsd.AnyType(),
+                ),
+                xsd.Element(
+                    'value',
+                    xsd.AnyType(),
+                ),
+            ]),
+        ),
+    )
+
+    Map = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Element(
+                'item',
+                xsd.AnyType(),
+                min_occurs=1,
+                max_occurs="unbounded"),
+        ]),
+        qname=etree.QName('{http://xml.apache.org/xml-soap}Map'))
+
+    header_Username = KeyValueData(xsd.AnyObject(xsd.String(), 'Username'), value=xsd.AnyObject(xsd.String(), 'abc'))
+    header_ShopId = KeyValueData(xsd.AnyObject(xsd.String(), 'ShopId'), value=xsd.AnyObject(xsd.Int(), 123))
+    auth = Map(item=[header_Username, header_ShopId])
+
+    header_LimitNum = KeyValueData(xsd.AnyObject(xsd.String(), 'LimitNum'), value=xsd.AnyObject(xsd.Int(), 2))
+    params = Map(item=[header_LimitNum])
+
+    container = schema.get_element('ns0:container')
+    obj = container(auth=auth, params=params)
+
+    result = render_node(container, obj)
+    expected = load_xml("""
+    <document>
+      <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+        <ns0:auth xmlns:ns1="http://xml.apache.org/xml-soap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns1:Map">
+          <item>
+            <key xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Username</key>
+            <value xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">abc</value>
+          </item>
+          <item>
+            <key xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">ShopId</key>
+            <value xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:int">123</value>
+          </item>
+        </ns0:auth>
+        <ns0:params xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:Map">
+          <item>
+            <key xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">LimitNum</key>
+            <value xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:int">2</value>
+          </item>
+        </ns0:params>
+      </ns0:container>
+    </document>
+    """)  # noqa
+    assert_nodes_equal(result, expected)
diff --git a/tests/test_xsd_extension.py b/tests/test_xsd_extension.py
new file mode 100644
index 0000000..d8c5a8f
--- /dev/null
+++ b/tests/test_xsd_extension.py
@@ -0,0 +1,597 @@
+import datetime
+import io
+
+from lxml import etree
+
+from tests.utils import DummyTransport, assert_nodes_equal, load_xml, render_node
+from zeep import xsd
+
+
+def test_simple_content_extension():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+
+          <xsd:element name="ShoeSize">
+            <xsd:complexType>
+              <xsd:simpleContent>
+                <xsd:extension base="xsd:integer">
+                  <xsd:attribute name="sizing" type="xsd:string" />
+                </xsd:extension>
+              </xsd:simpleContent>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """.strip()))
+    shoe_type = schema.get_element('{http://tests.python-zeep.org/}ShoeSize')
+
+    obj = shoe_type(20, sizing='EUR')
+
+    node = render_node(shoe_type, obj)
+    expected = """
+        <document>
+            <ns0:ShoeSize
+                xmlns:ns0="http://tests.python-zeep.org/"
+                sizing="EUR">20</ns0:ShoeSize>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+    obj = shoe_type.parse(node[0], schema)
+    assert obj._value_1 == 20
+    assert obj.sizing == 'EUR'
+
+
+def test_complex_content_sequence_extension():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+
+            <xsd:complexType name="Address">
+              <xsd:complexContent>
+                <xsd:extension base="tns:Name">
+                  <xsd:sequence>
+                    <xsd:element name="country" type="xsd:string"/>
+                  </xsd:sequence>
+                </xsd:extension>
+              </xsd:complexContent>
+            </xsd:complexType>
+          <xsd:element name="Address" type="tns:Address"/>
+
+          <xsd:complexType name="Name">
+            <xsd:sequence>
+              <xsd:element name="first_name" type="xsd:string"/>
+              <xsd:element name="last_name" type="xsd:string"/>
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:schema>
+    """))
+    address_type = schema.get_element('{http://tests.python-zeep.org/}Address')
+
+    obj = address_type(
+        first_name='foo', last_name='bar', country='The Netherlands')
+
+    node = etree.Element('document')
+    address_type.render(node, obj)
+    expected = """
+        <document>
+            <ns0:Address xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:first_name>foo</ns0:first_name>
+                <ns0:last_name>bar</ns0:last_name>
+                <ns0:country>The Netherlands</ns0:country>
+            </ns0:Address>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_complex_content_with_recursive_elements():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+
+            <xsd:complexType name="Pet">
+              <xsd:complexContent>
+                <xsd:extension base="tns:Name">
+                  <xsd:sequence>
+                    <xsd:element name="children" type="tns:Pet"/>
+                  </xsd:sequence>
+                </xsd:extension>
+              </xsd:complexContent>
+            </xsd:complexType>
+          <xsd:element name="Pet" type="tns:Pet"/>
+
+          <xsd:complexType name="Name">
+            <xsd:sequence>
+              <xsd:element name="name" type="xsd:string"/>
+              <xsd:element name="common_name" type="xsd:string"/>
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:schema>
+    """))
+    pet_type = schema.get_element('{http://tests.python-zeep.org/}Pet')
+    assert(pet_type.signature() == 'name: xsd:string, common_name: xsd:string, children: Pet')
+
+    obj = pet_type(
+        name='foo', common_name='bar')
+
+    node = etree.Element('document')
+    pet_type.render(node, obj)
+    expected = """
+        <document>
+            <ns0:Pet xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:name>foo</ns0:name>
+                <ns0:common_name>bar</ns0:common_name>
+                <ns0:children/>
+            </ns0:Pet>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_complex_content_sequence_extension_2():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+
+          <xsd:element name="container" type="tns:baseResponse"/>
+          <xsd:complexType name="baseResponse">
+            <xsd:sequence>
+              <xsd:element name="item-1" type="xsd:string"/>
+              <xsd:element name="item-2" type="xsd:string"/>
+            </xsd:sequence>
+          </xsd:complexType>
+
+          <xsd:complexType name="response">
+            <xsd:complexContent>
+              <xsd:extension base="tns:baseResponse">
+                <xsd:sequence>
+                  <xsd:element name="item-3" type="xsd:string"/>
+                </xsd:sequence>
+              </xsd:extension>
+            </xsd:complexContent>
+          </xsd:complexType>
+        </xsd:schema>
+    """))
+    elm_cls = schema.get_element('{http://tests.python-zeep.org/}container')
+
+    node = load_xml("""
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/"
+                       xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
+                       i:type="ns0:response">
+            <ns0:item-1>item-1</ns0:item-1>
+            <ns0:item-2>item-2</ns0:item-2>
+            <ns0:item-3>item-3</ns0:item-3>
+        </ns0:container>
+    """)
+    data = elm_cls.parse(node, schema)
+    assert data['item-1'] == 'item-1'
+    assert data['item-2'] == 'item-2'
+    assert data['item-3'] == 'item-3'
+
+
+def test_complex_type_with_extension_optional():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+
+          <xsd:complexType name="containerType">
+            <xsd:complexContent>
+              <xsd:extension base="tns:base">
+                <xsd:sequence>
+                  <xsd:element name="main_1" type="xsd:string"/>
+                </xsd:sequence>
+              </xsd:extension>
+            </xsd:complexContent>
+          </xsd:complexType>
+          <xsd:element name="container" type="tns:containerType"/>
+
+          <xsd:complexType name="base">
+            <xsd:sequence>
+              <xsd:element minOccurs="0" name="base_1" type="tns:baseType"/>
+              <xsd:element minOccurs="0" name="base_2" type="xsd:string"/>
+            </xsd:sequence>
+          </xsd:complexType>
+
+          <xsd:complexType name="baseType">
+            <xsd:sequence>
+              <xsd:element minOccurs="0" name="base_1_1" type="xsd:string"/>
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:schema>
+    """))
+    container_elm = schema.get_element('{http://tests.python-zeep.org/}container')
+    obj = container_elm(main_1='foo')
+
+    node = etree.Element('document')
+    container_elm.render(node, obj)
+    expected = """
+        <document>
+            <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:main_1>foo</ns0:main_1>
+            </ns0:container>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+    assert_nodes_equal(expected, node)
+    item = container_elm.parse(node.getchildren()[0], schema)
+    assert item.main_1 == 'foo'
+
+
+def test_complex_with_simple():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="Address">
+            <xsd:complexType>
+              <xsd:simpleContent>
+                <xsd:extension base="tns:DateTimeType">
+                  <xsd:attribute name="name" type="xsd:token"/>
+                </xsd:extension>
+              </xsd:simpleContent>
+            </xsd:complexType>
+          </xsd:element>
+
+          <xsd:simpleType name="DateTimeType">
+            <xsd:restriction base="xsd:dateTime"/>
+          </xsd:simpleType>
+        </xsd:schema>
+    """))
+    address_type = schema.get_element('ns0:Address')
+
+    assert address_type.type.signature()
+    val = datetime.datetime(2016, 5, 29, 11, 13, 45)
+    obj = address_type(val, name='foobie')
+
+    expected = """
+      <document>
+        <ns0:Address xmlns:ns0="http://tests.python-zeep.org/"
+            name="foobie">2016-05-29T11:13:45</ns0:Address>
+      </document>
+    """
+    node = etree.Element('document')
+    address_type.render(node, obj)
+    assert_nodes_equal(expected, node)
+
+
+def test_sequence_with_type():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema
+                xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+
+          <complexType name="base" abstract="true">
+            <sequence>
+              <element name="name" type="xsd:string" minOccurs="0"/>
+            </sequence>
+          </complexType>
+
+          <complexType name="subtype">
+            <complexContent>
+              <extension base="tns:base">
+                <attribute name="attr_1" type="xsd:string"/>
+              </extension>
+            </complexContent>
+          </complexType>
+
+          <complexType name="polytype">
+            <sequence>
+              <element name="item" type="tns:base" maxOccurs="unbounded" minOccurs="0"/>
+            </sequence>
+          </complexType>
+
+          <element name="Seq" type="tns:polytype"/>
+        </schema>
+    """))
+    seq = schema.get_type('ns0:polytype')
+    sub_type = schema.get_type('ns0:subtype')
+    value = seq(item=[sub_type(attr_1='test', name='name')])
+
+    node = etree.Element('document')
+    seq.render(node, value)
+
+    expected = """
+      <document>
+        <ns0:item
+            xmlns:ns0="http://tests.python-zeep.org/"
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+            attr_1="test" xsi:type="ns0:subtype">
+          <ns0:name>name</ns0:name>
+        </ns0:item>
+      </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_complex_simple_content():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:tns="http://tests.python-zeep.org/"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+          <xsd:element name="value" type="tns:UUID"/>
+
+          <xsd:complexType name="UUID">
+            <xsd:simpleContent>
+              <xsd:extension base="tns:UUID.Content">
+                <xsd:attribute name="schemeID">
+                  <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                      <xsd:maxLength value="60"/>
+                      <xsd:minLength value="1"/>
+                    </xsd:restriction>
+                  </xsd:simpleType>
+                </xsd:attribute>
+                <xsd:attribute name="schemeAgencyID">
+                  <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                      <xsd:maxLength value="60"/>
+                      <xsd:minLength value="1"/>
+                    </xsd:restriction>
+                  </xsd:simpleType>
+                </xsd:attribute>
+              </xsd:extension>
+            </xsd:simpleContent>
+          </xsd:complexType>
+          <xsd:simpleType name="UUID.Content">
+            <xsd:restriction base="xsd:token">
+              <xsd:maxLength value="36"/>
+              <xsd:minLength value="36"/>
+              <xsd:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"/>
+            </xsd:restriction>
+          </xsd:simpleType>
+        </xsd:schema>
+    """))  # noqa
+    value_elm = schema.get_element('ns0:value')
+    value = value_elm('00163e0c-0ea1-1ed6-93af-e818529bc1f1')
+
+    node = etree.Element('document')
+    value_elm.render(node, value)
+    expected = """
+      <document>
+        <ns0:value xmlns:ns0="http://tests.python-zeep.org/">00163e0c-0ea1-1ed6-93af-e818529bc1f1</ns0:value>
+      </document>
+    """  # noqa
+    assert_nodes_equal(expected, node)
+
+    item = value_elm.parse(node.getchildren()[0], schema)
+    assert item._value_1 == '00163e0c-0ea1-1ed6-93af-e818529bc1f1'
+
+
+def test_issue_221():
+    transport = DummyTransport()
+    transport.bind(
+        'https://www.w3.org/TR/xmldsig-core/xmldsig-core-schema.xsd',
+        load_xml(io.open('tests/wsdl_files/xmldsig-core-schema.xsd', 'r').read().encode('utf-8')))
+
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <import namespace="http://www.w3.org/2000/09/xmldsig#"
+                  schemaLocation="https://www.w3.org/TR/xmldsig-core/xmldsig-core-schema.xsd"/>
+          <complexType name="BaseType">
+            <sequence>
+              <element ref="ds:Signature" minOccurs="0"/>
+            </sequence>
+            <attribute name="Id"/>
+          </complexType>
+          <element name="exportOrgRegistryRequest">
+            <complexType>
+              <complexContent>
+                <extension base="tns:BaseType">
+                  <sequence>
+                    <element name="SearchCriteria" maxOccurs="100">
+                      <complexType>
+                        <sequence>
+                          <choice>
+                            <choice>
+                              <element ref="tns:OGRNIP"/>
+                              <sequence>
+                                <element name="OGRN" type="string"/>
+                                <element name="KPP" type="string" minOccurs="0"/>
+                              </sequence>
+                            </choice>
+                            <element ref="tns:orgVersionGUID"/>
+                            <element ref="tns:orgRootEntityGUID"/>
+                          </choice>
+                          <element name="isRegistered" type="boolean" fixed="true" minOccurs="0">
+                          </element>
+                        </sequence>
+                      </complexType>
+                    </element>
+                    <element name="lastEditingDateFrom" type="date" minOccurs="0"/>
+                  </sequence>
+                </extension>
+              </complexContent>
+            </complexType>
+          </element>
+          <simpleType name="OGRNIPType">
+            <restriction base="string">
+              <length value="13"/>
+            </restriction>
+          </simpleType>
+          <element name="OGRNIP" type="tns:OGRNIPType"/>
+          <element name="orgVersionGUID" type="tns:GUIDType"/>
+          <element name="orgRootEntityGUID" type="tns:GUIDType"/>
+          <simpleType name="GUIDType">
+            <restriction base="string">
+              <pattern value="([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}"/>
+            </restriction>
+          </simpleType>x
+        </schema>
+    """), transport=transport)
+
+    schema.set_ns_prefix('tns', 'http://tests.python-zeep.org/')
+    elm = schema.get_element('tns:exportOrgRegistryRequest')
+
+    # Args
+    obj = elm(None, {'OGRN': '123123123123', 'isRegistered': True})
+    node = etree.Element('document')
+    elm.render(node, obj)
+    expected = """
+      <document>
+        <ns0:exportOrgRegistryRequest xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:SearchCriteria>
+            <ns0:OGRN>123123123123</ns0:OGRN>
+            <ns0:isRegistered>true</ns0:isRegistered>
+          </ns0:SearchCriteria>
+        </ns0:exportOrgRegistryRequest>
+      </document>
+    """
+    assert_nodes_equal(expected, node)
+
+    obj = elm(SearchCriteria={'orgVersionGUID': '1234', 'isRegistered': False})
+    node = etree.Element('document')
+    elm.render(node, obj)
+    expected = """
+      <document>
+        <ns0:exportOrgRegistryRequest xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:SearchCriteria>
+            <ns0:orgVersionGUID>1234</ns0:orgVersionGUID>
+            <ns0:isRegistered>false</ns0:isRegistered>
+          </ns0:SearchCriteria>
+        </ns0:exportOrgRegistryRequest>
+      </document>
+    """
+    assert_nodes_equal(expected, node)
+
+    obj = elm(SearchCriteria={'OGRNIP': '123123123123', 'isRegistered': True})
+    node = etree.Element('document')
+    elm.render(node, obj)
+    expected = """
+      <document>
+        <ns0:exportOrgRegistryRequest xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:SearchCriteria>
+            <ns0:OGRNIP>123123123123</ns0:OGRNIP>
+            <ns0:isRegistered>true</ns0:isRegistered>
+          </ns0:SearchCriteria>
+        </ns0:exportOrgRegistryRequest>
+      </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_complex_content_extension_with_sequence():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+
+            <xsd:complexType name="Package">
+              <xsd:complexContent>
+                <xsd:extension base="tns:AbstractPackage">
+                  <xsd:attribute name="id" type="xsd:string"/>
+                </xsd:extension>
+              </xsd:complexContent>
+            </xsd:complexType>
+
+            <xsd:complexType name="SpecialPackage">
+              <xsd:complexContent>
+                <xsd:extension base="tns:Package">
+                    <xsd:sequence>
+                        <xsd:element name="otherElement" type="xsd:string"/>
+                    </xsd:sequence>
+                </xsd:extension>
+              </xsd:complexContent>
+            </xsd:complexType>
+
+            <xsd:complexType name="AbstractPackage">
+              <xsd:attribute name="pkg_id" type="xsd:string"/>
+            </xsd:complexType>
+
+          <xsd:element name="SpecialPackage" type="tns:SpecialPackage"/>
+        </xsd:schema>
+    """))
+    address_type = schema.get_element('{http://tests.python-zeep.org/}SpecialPackage')
+
+    obj = address_type(
+        id='testString', pkg_id='nameId')
+
+    node = etree.Element('document')
+    address_type.render(node, obj)
+    expected = """
+        <document>
+            <ns0:SpecialPackage xmlns:ns0="http://tests.python-zeep.org/" pkg_id="nameId" id="testString">
+                <ns0:otherElement/>
+            </ns0:SpecialPackage>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_extension_abstract_complex_type():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+
+            <xsd:complexType name="Package" abstract="true"/>
+
+            <xsd:complexType name="SpecialPackage">
+              <xsd:complexContent>
+                <xsd:extension base="tns:Package">
+                    <xsd:sequence>
+                        <xsd:element name="item" type="xsd:string"/>
+                    </xsd:sequence>
+                </xsd:extension>
+              </xsd:complexContent>
+            </xsd:complexType>
+
+          <xsd:element name="SpecialPackage" type="tns:SpecialPackage"/>
+        </xsd:schema>
+    """))
+    package_cls = schema.get_element('{http://tests.python-zeep.org/}SpecialPackage')
+
+    obj = package_cls(item='foo')
+
+    node = etree.Element('document')
+    package_cls.render(node, obj)
+    expected = """
+        <document>
+            <ns0:SpecialPackage xmlns:ns0="http://tests.python-zeep.org/">
+                <ns0:item>foo</ns0:item>
+            </ns0:SpecialPackage>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
diff --git a/tests/test_xsd_integration.py b/tests/test_xsd_integration.py
index 06df987..64d9847 100644
--- a/tests/test_xsd_integration.py
+++ b/tests/test_xsd_integration.py
@@ -1,3 +1,5 @@
+import copy
+
 import pytest
 from lxml import etree
 
@@ -125,7 +127,6 @@ def test_array():
     """
     node = etree.Element('document', nsmap=schema._prefix_map_custom)
     address_type.render(node, obj)
-    print(etree.tostring(node))
     assert_nodes_equal(expected, node)
 
 
@@ -902,3 +903,51 @@ def test_empty_xmlns():
     """)
     item = container_elm.parse(node, schema)
     assert item._value_1 == 'foo'
+
+
+def test_keep_objects_intact():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                attributeFormDefault="qualified"
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/">
+          <xsd:element name="Address">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="name" type="xsd:string"/>
+                <xsd:element minOccurs="0" name="optional" type="xsd:string"/>
+                <xsd:element name="container" nillable="true" type="tns:Container"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+
+          <xsd:complexType name="Container">
+            <xsd:sequence>
+              <xsd:element maxOccurs="unbounded" minOccurs="0" name="service"
+                           nillable="true" type="tns:ServiceRequestType"/>
+            </xsd:sequence>
+          </xsd:complexType>
+
+          <xsd:complexType name="ServiceRequestType">
+            <xsd:sequence>
+              <xsd:element name="name" type="xsd:string"/>
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:schema>
+    """.strip())
+
+    schema = xsd.Schema(node)
+    address_type = schema.get_element('{http://tests.python-zeep.org/}Address')
+    obj = address_type(name='foo', container={'service': [{'name': 'foo'}]})
+
+    org_obj = copy.deepcopy(obj)
+
+    node = etree.Element('document')
+    address_type.render(node, obj)
+
+    print(org_obj)
+    print(obj)
+    assert org_obj['container']['service'] == obj['container']['service']
diff --git a/tests/test_xsd_parse.py b/tests/test_xsd_parse.py
index c7f959e..3357d7c 100644
--- a/tests/test_xsd_parse.py
+++ b/tests/test_xsd_parse.py
@@ -30,6 +30,33 @@ def test_sequence_parse_basic():
     assert obj.item_2 == 'bar'
 
 
+def test_sequence_parse_max_occurs_infinite_loop():
+    custom_type = xsd.Element(
+        etree.QName('http://tests.python-zeep.org/', 'authentication'),
+        xsd.ComplexType(
+            xsd.Sequence([
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_1'),
+                    xsd.String()),
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_2'),
+                    xsd.String()),
+            ], max_occurs='unbounded')
+        ))
+    expected = etree.fromstring("""
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/">
+          <ns0:item_1>foo</ns0:item_1>
+          <ns0:item_2>bar</ns0:item_2>
+        </ns0:container>
+    """)
+    obj = custom_type.parse(expected, None)
+    assert obj._value_1 == [
+        {
+            'item_1': 'foo',
+            'item_2': 'bar',
+        }
+    ]
+
 def test_sequence_parse_basic_with_attrs():
     custom_element = xsd.Element(
         etree.QName('http://tests.python-zeep.org/', 'authentication'),
diff --git a/tests/test_xsd_schemas.py b/tests/test_xsd_schemas.py
new file mode 100644
index 0000000..269c3fe
--- /dev/null
+++ b/tests/test_xsd_schemas.py
@@ -0,0 +1,656 @@
+import pytest
+from lxml import etree
+
+from tests.utils import DummyTransport, load_xml
+from zeep import exceptions, xsd
+from zeep.xsd.builtins import Schema as Schema
+from zeep.exceptions import ZeepWarning
+
+
+def test_default_types():
+    schema = xsd.Schema()
+    xsd_string = schema.get_type('{http://www.w3.org/2001/XMLSchema}string')
+    assert xsd_string == xsd.String()
+
+
+def test_default_types_not_found():
+    schema = xsd.Schema()
+    with pytest.raises(exceptions.LookupError):
+        schema.get_type('{http://www.w3.org/2001/XMLSchema}bar')
+
+
+def test_default_elements():
+    schema = xsd.Schema()
+    xsd_schema = schema.get_element('{http://www.w3.org/2001/XMLSchema}schema')
+    isinstance(xsd_schema, Schema)
+
+
+def test_default_elements_not_found():
+    schema = xsd.Schema()
+    with pytest.raises(exceptions.LookupError):
+        schema.get_element('{http://www.w3.org/2001/XMLSchema}bar')
+
+
+def test_invalid_namespace_handling():
+    schema = xsd.Schema()
+    qname = '{http://tests.python-zeep.org/404}foo'
+
+    with pytest.raises(exceptions.NamespaceError) as exc:
+        schema.get_element(qname)
+    assert qname in str(exc.value.message)
+
+    with pytest.raises(exceptions.NamespaceError) as exc:
+        schema.get_type(qname)
+    assert qname in str(exc.value.message)
+
+    with pytest.raises(exceptions.NamespaceError) as exc:
+        schema.get_group(qname)
+    assert qname in str(exc.value.message)
+
+    with pytest.raises(exceptions.NamespaceError) as exc:
+        schema.get_attribute(qname)
+    assert qname in str(exc.value.message)
+
+    with pytest.raises(exceptions.NamespaceError) as exc:
+        schema.get_attribute_group(qname)
+    assert qname in str(exc.value.message)
+
+
+def test_invalid_localname_handling():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+        </xs:schema>
+    """))
+
+    qname = '{http://tests.python-zeep.org/}foo'
+    namespace = 'http://tests.python-zeep.org/'
+    localname = 'foo'
+
+    with pytest.raises(exceptions.LookupError) as exc:
+        schema.get_element(qname)
+    assert namespace in str(exc.value.message)
+    assert localname in str(exc.value.message)
+
+    with pytest.raises(exceptions.LookupError) as exc:
+        schema.get_type(qname)
+    assert namespace in str(exc.value.message)
+    assert localname in str(exc.value.message)
+
+    with pytest.raises(exceptions.LookupError) as exc:
+        schema.get_group(qname)
+    assert namespace in str(exc.value.message)
+    assert localname in str(exc.value.message)
+
+    with pytest.raises(exceptions.LookupError) as exc:
+        schema.get_attribute(qname)
+    assert namespace in str(exc.value.message)
+    assert localname in str(exc.value.message)
+
+    with pytest.raises(exceptions.LookupError) as exc:
+        schema.get_attribute_group(qname)
+    assert namespace in str(exc.value.message)
+    assert localname in str(exc.value.message)
+
+
+def test_schema_repr_none():
+    schema = xsd.Schema()
+    assert repr(schema) == "<Schema(location='<none>')>"
+
+
+def test_schema_repr_val():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+        </xs:schema>
+    """))
+    assert repr(schema) == "<Schema(location=None)>"
+
+
+def test_schema_doc_repr_val():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+        </xs:schema>
+    """))
+    doc = schema._get_schema_document('http://tests.python-zeep.org/')
+    assert repr(doc) == "<SchemaDocument(location=None, tns='http://tests.python-zeep.org/', is_empty=True)>"
+
+
+def test_multiple_extension():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            xmlns:b="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/b.xsd"
+                namespace="http://tests.python-zeep.org/b"/>
+
+            <xs:complexType name="type_a">
+              <xs:complexContent>
+                <xs:extension base="b:type_b"/>
+              </xs:complexContent>
+            </xs:complexType>
+            <xs:element name="typetje" type="tns:type_a"/>
+
+        </xs:schema>
+    """.strip())
+
+    node_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/b"
+            targetNamespace="http://tests.python-zeep.org/b"
+            xmlns:c="http://tests.python-zeep.org/c"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/c.xsd"
+                namespace="http://tests.python-zeep.org/c"/>
+
+            <xs:complexType name="type_b">
+              <xs:complexContent>
+                <xs:extension base="c:type_c"/>
+              </xs:complexContent>
+            </xs:complexType>
+        </xs:schema>
+    """.strip())
+
+    node_c = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/c"
+            targetNamespace="http://tests.python-zeep.org/c"
+            elementFormDefault="qualified">
+
+            <xs:complexType name="type_c">
+              <xs:complexContent>
+                <xs:extension base="tns:type_d"/>
+              </xs:complexContent>
+            </xs:complexType>
+
+            <xs:complexType name="type_d">
+                <xs:attribute name="wat" type="xs:string" />
+            </xs:complexType>
+        </xs:schema>
+    """.strip())
+    etree.XMLSchema(node_c)
+
+    transport = DummyTransport()
+    transport.bind('http://tests.python-zeep.org/b.xsd', node_b)
+    transport.bind('http://tests.python-zeep.org/c.xsd', node_c)
+
+    schema = xsd.Schema(node_a, transport=transport)
+    type_a = schema.get_type('ns0:type_a')
+    type_a(wat='x')
+
+
+def test_global_element_and_type():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            xmlns:b="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/b.xsd"
+                namespace="http://tests.python-zeep.org/b"/>
+
+            <xs:complexType name="refs">
+              <xs:sequence>
+                <xs:element ref="b:ref_elm"/>
+              </xs:sequence>
+              <xs:attribute ref="b:ref_attr"/>
+            </xs:complexType>
+
+        </xs:schema>
+    """.strip())
+
+    node_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/b"
+            targetNamespace="http://tests.python-zeep.org/b"
+            xmlns:c="http://tests.python-zeep.org/c"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/c.xsd"
+                namespace="http://tests.python-zeep.org/c"/>
+
+            <xs:element name="ref_elm" type="xs:string"/>
+            <xs:attribute name="ref_attr" type="xs:string"/>
+        </xs:schema>
+    """.strip())
+
+    node_c = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/c"
+            targetNamespace="http://tests.python-zeep.org/c"
+            elementFormDefault="qualified">
+
+            <xs:complexType name="type_a">
+              <xs:sequence>
+                <xs:element name="item_a" type="xs:string"/>
+              </xs:sequence>
+            </xs:complexType>
+            <xs:element name="item" type="xs:string"/>
+        </xs:schema>
+    """.strip())
+    etree.XMLSchema(node_c)
+
+    transport = DummyTransport()
+    transport.bind('http://tests.python-zeep.org/b.xsd', node_b)
+    transport.bind('http://tests.python-zeep.org/c.xsd', node_c)
+
+    schema = xsd.Schema(node_a, transport=transport)
+    type_a = schema.get_type('{http://tests.python-zeep.org/c}type_a')
+
+    type_a = schema.get_type('{http://tests.python-zeep.org/c}type_a')
+    type_a(item_a='x')
+
+    elm = schema.get_element('{http://tests.python-zeep.org/c}item')
+    elm('x')
+
+    elm = schema.get_type('{http://tests.python-zeep.org/a}refs')
+    elm(ref_elm='foo', ref_attr='bar')
+
+
+def test_cyclic_imports():
+    schema_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            xmlns:b="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/b.xsd"
+                namespace="http://tests.python-zeep.org/b"/>
+        </xs:schema>
+    """.strip())
+
+    schema_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/b"
+            targetNamespace="http://tests.python-zeep.org/b"
+            xmlns:c="http://tests.python-zeep.org/c"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/c.xsd"
+                namespace="http://tests.python-zeep.org/c"/>
+        </xs:schema>
+    """.strip())
+
+    schema_c = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/c"
+            targetNamespace="http://tests.python-zeep.org/c"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/a.xsd"
+                namespace="http://tests.python-zeep.org/a"/>
+        </xs:schema>
+    """.strip())
+
+    transport = DummyTransport()
+    transport.bind('http://tests.python-zeep.org/a.xsd', schema_a)
+    transport.bind('http://tests.python-zeep.org/b.xsd', schema_b)
+    transport.bind('http://tests.python-zeep.org/c.xsd', schema_c)
+    xsd.Schema(schema_a, transport=transport, location='http://tests.python-zeep.org/a.xsd')
+
+
+def test_get_type_through_import():
+    schema_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            xmlns:b="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/b.xsd"
+                namespace="http://tests.python-zeep.org/b"/>
+            <xs:element name="foo" type="b:bar"/>
+
+        </xs:schema>
+    """.strip())
+
+    schema_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/b"
+            targetNamespace="http://tests.python-zeep.org/b"
+            xmlns:c="http://tests.python-zeep.org/c"
+            elementFormDefault="qualified">
+
+            <xs:complexType name="bar"/>
+
+        </xs:schema>
+    """.strip())
+
+    transport = DummyTransport()
+    transport.bind('http://tests.python-zeep.org/a.xsd', schema_a)
+    transport.bind('http://tests.python-zeep.org/b.xsd', schema_b)
+    xsd.Schema(schema_a, transport=transport)
+
+
+def test_duplicate_target_namespace():
+    schema_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/b.xsd"
+                namespace="http://tests.python-zeep.org/duplicate"/>
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/c.xsd"
+                namespace="http://tests.python-zeep.org/duplicate"/>
+        </xs:schema>
+    """.strip())
+
+    schema_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            targetNamespace="http://tests.python-zeep.org/duplicate"
+            elementFormDefault="qualified">
+        </xsd:schema>
+    """.strip())
+
+    schema_c = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            targetNamespace="http://tests.python-zeep.org/duplicate"
+            elementFormDefault="qualified">
+        </xsd:schema>
+    """.strip())
+
+    transport = DummyTransport()
+    transport.bind('http://tests.python-zeep.org/a.xsd', schema_a)
+    transport.bind('http://tests.python-zeep.org/b.xsd', schema_b)
+    transport.bind('http://tests.python-zeep.org/c.xsd', schema_c)
+    with pytest.warns(ZeepWarning):
+        xsd.Schema(schema_a, transport=transport)
+
+
+def test_multiple_no_namespace():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            elementFormDefault="qualified">
+
+          <xsd:import schemaLocation="http://tests.python-zeep.org/b.xsd"/>
+          <xsd:import schemaLocation="http://tests.python-zeep.org/c.xsd"/>
+        </xsd:schema>
+    """.strip())
+
+    node_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            elementFormDefault="qualified">
+        </xsd:schema>
+    """.strip())
+
+    transport = DummyTransport()
+    transport.bind('http://tests.python-zeep.org/b.xsd', node_b)
+    transport.bind('http://tests.python-zeep.org/c.xsd', node_b)
+    with pytest.warns(ZeepWarning):
+        xsd.Schema(node_a, transport=transport)
+
+
+def test_multiple_only_target_ns():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            elementFormDefault="qualified">
+
+          <xsd:import schemaLocation="http://tests.python-zeep.org/b.xsd"/>
+          <xsd:import schemaLocation="http://tests.python-zeep.org/c.xsd"/>
+        </xsd:schema>
+    """.strip())
+
+    node_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            elementFormDefault="qualified"
+            targetNamespace="http://tests.python-zeep.org/duplicate-ns">
+        </xsd:schema>
+    """.strip())
+
+    transport = DummyTransport()
+    transport.bind('http://tests.python-zeep.org/b.xsd', node_b)
+    transport.bind('http://tests.python-zeep.org/c.xsd', node_b)
+    with pytest.warns(ZeepWarning):
+        xsd.Schema(node_a, transport=transport)
+
+
+def test_schema_error_handling():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            xmlns:b="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+
+        </xs:schema>
+    """.strip())
+    transport = DummyTransport()
+    schema = xsd.Schema(node_a, transport=transport)
+
+    with pytest.raises(ValueError):
+        schema.get_element('nonexisting:something')
+    with pytest.raises(ValueError):
+        schema.get_type('nonexisting:something')
+    with pytest.raises(exceptions.NamespaceError):
+        schema.get_element('{nonexisting}something')
+    with pytest.raises(exceptions.NamespaceError):
+        schema.get_type('{nonexisting}something')
+    with pytest.raises(exceptions.LookupError):
+        schema.get_element('ns0:something')
+    with pytest.raises(exceptions.LookupError):
+        schema.get_type('ns0:something')
+
+
+def test_schema_import_xmlsoap():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            xmlns:b="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+          <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
+        </xsd:schema>
+    """.strip())
+    transport = DummyTransport()
+    xsd.Schema(node_a, transport=transport)
+
+
+def test_schema_import_unresolved():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            xmlns:b="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+          <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
+        </xsd:schema>
+    """.strip())
+    transport = DummyTransport()
+    xsd.Schema(node_a, transport=transport)
+
+
+def test_no_target_namespace():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            elementFormDefault="qualified">
+
+          <xsd:import schemaLocation="http://tests.python-zeep.org/b.xsd"/>
+
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element ref="bla"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+
+        </xsd:schema>
+    """.strip())
+
+    node_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            elementFormDefault="qualified">
+            <xsd:element name="bla" type="xsd:string"/>
+        </xsd:schema>
+    """.strip())
+
+    transport = DummyTransport()
+    transport.bind('http://tests.python-zeep.org/b.xsd', node_b)
+    xsd.Schema(node_a, transport=transport)
+
+
+def test_include_recursion():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            xmlns:b="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+
+            <xs:import
+                schemaLocation="http://tests.python-zeep.org/b.xsd"
+                namespace="http://tests.python-zeep.org/b"/>
+
+        </xs:schema>
+    """.strip())
+
+    node_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/b"
+            targetNamespace="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+
+            <xs:include schemaLocation="http://tests.python-zeep.org/c.xsd"/>
+            <xs:element name="bar" type="xs:string"/>
+        </xs:schema>
+    """.strip())
+
+    node_c = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/b"
+            targetNamespace="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+
+            <xs:include schemaLocation="http://tests.python-zeep.org/b.xsd"/>
+
+            <xs:element name="foo" type="xs:string"/>
+        </xs:schema>
+    """.strip())
+
+    transport = DummyTransport()
+    transport.bind('http://tests.python-zeep.org/b.xsd', node_b)
+    transport.bind('http://tests.python-zeep.org/c.xsd', node_c)
+
+    schema = xsd.Schema(node_a, transport=transport)
+    schema.get_element('{http://tests.python-zeep.org/b}foo')
+    schema.get_element('{http://tests.python-zeep.org/b}bar')
+
+
+def test_merge():
+    node_a = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/a"
+            targetNamespace="http://tests.python-zeep.org/a"
+            xmlns:b="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+          <xs:element name="foo" type="xs:string"/>
+        </xs:schema>
+    """.strip())
+
+    node_b = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xs:schema
+            xmlns:xs="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/b"
+            targetNamespace="http://tests.python-zeep.org/b"
+            elementFormDefault="qualified">
+          <xs:element name="foo" type="xs:int"/>
+        </xs:schema>
+    """.strip())
+
+    schema_a = xsd.Schema(node_a)
+    schema_b = xsd.Schema(node_b)
+    schema_a.merge(schema_b)
+
+    schema_a.get_element('{http://tests.python-zeep.org/a}foo')
+    schema_a.get_element('{http://tests.python-zeep.org/b}foo')
diff --git a/tests/test_xsd_signatures.py b/tests/test_xsd_signatures.py
new file mode 100644
index 0000000..0040d6a
--- /dev/null
+++ b/tests/test_xsd_signatures.py
@@ -0,0 +1,187 @@
+from lxml import etree
+
+from zeep import xsd
+
+
+def test_signature_complex_type_choice():
+    custom_type = xsd.Element(
+        etree.QName('http://tests.python-zeep.org/', 'authentication'),
+        xsd.ComplexType(
+            xsd.Choice([
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_1'),
+                    xsd.String()),
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_2'),
+                    xsd.String()),
+            ])
+        ))
+    assert custom_type.signature() == '({item_1: xsd:string} | {item_2: xsd:string})'
+
+
+def test_signature_complex_type_choice_sequence():
+    custom_type = xsd.Element(
+        etree.QName('http://tests.python-zeep.org/', 'authentication'),
+        xsd.ComplexType(
+            xsd.Choice([
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_1'),
+                    xsd.String()),
+                xsd.Sequence([
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_2_1'),
+                        xsd.String()),
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_2_2'),
+                        xsd.String()),
+                ])
+            ])
+        ))
+    assert custom_type.signature() == (
+        '({item_1: xsd:string} | {item_2_1: xsd:string, item_2_2: xsd:string})')
+
+
+def test_signature_nested_sequences():
+    custom_type = xsd.Element(
+        etree.QName('http://tests.python-zeep.org/', 'authentication'),
+        xsd.ComplexType(
+            xsd.Sequence([
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_1'),
+                    xsd.String()),
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_2'),
+                    xsd.String()),
+                xsd.Sequence([
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_3'),
+                        xsd.String()),
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_4'),
+                        xsd.String()),
+                ]),
+                xsd.Choice([
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_5'),
+                        xsd.String()),
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_6'),
+                        xsd.String()),
+                    xsd.Sequence([
+                        xsd.Element(
+                            etree.QName('http://tests.python-zeep.org/', 'item_5'),
+                            xsd.String()),
+                        xsd.Element(
+                            etree.QName('http://tests.python-zeep.org/', 'item_6'),
+                            xsd.String()),
+                    ])
+                ])
+            ])
+        ))
+
+    assert custom_type.signature() == (
+        'item_1: xsd:string, item_2: xsd:string, item_3: xsd:string, item_4: xsd:string, ({item_5: xsd:string} | {item_6: xsd:string} | {item_5: xsd:string, item_6: xsd:string})'  # noqa
+    )
+
+
+def test_signature_nested_sequences_multiple():
+    custom_type = xsd.Element(
+        etree.QName('http://tests.python-zeep.org/', 'authentication'),
+        xsd.ComplexType(
+            xsd.Sequence([
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_1'),
+                    xsd.String()),
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_2'),
+                    xsd.String()),
+                xsd.Sequence([
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_3'),
+                        xsd.String()),
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_4'),
+                        xsd.String()),
+                ]),
+                xsd.Choice([
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_5'),
+                        xsd.String()),
+                    xsd.Element(
+                        etree.QName('http://tests.python-zeep.org/', 'item_6'),
+                        xsd.String()),
+                    xsd.Sequence([
+                        xsd.Element(
+                            etree.QName('http://tests.python-zeep.org/', 'item_5'),
+                            xsd.String()),
+                        xsd.Element(
+                            etree.QName('http://tests.python-zeep.org/', 'item_6'),
+                            xsd.String()),
+                    ])
+                ], min_occurs=2, max_occurs=3)
+            ])
+        ))
+
+    assert custom_type.signature() == (
+        'item_1: xsd:string, item_2: xsd:string, item_3: xsd:string, item_4: xsd:string, _value_1: ({item_5: xsd:string} | {item_6: xsd:string} | {item_5: xsd:string, item_6: xsd:string})[]'  # noqa
+    )
+
+
+def test_signature_complex_type_any():
+    custom_type = xsd.Element(
+        etree.QName('http://tests.python-zeep.org/', 'authentication'),
+        xsd.ComplexType(
+            xsd.Choice([
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_1'),
+                    xsd.String()),
+                xsd.Any()
+            ])
+        ))
+    assert custom_type.signature() == '({item_1: xsd:string} | {_value_1: ANY})'
+    custom_type(item_1='foo')
+
+
+def test_signature_complex_type_sequence_with_any():
+    custom_type = xsd.Element(
+        etree.QName('http://tests.python-zeep.org/', 'authentication'),
+        xsd.ComplexType(
+            xsd.Choice([
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_1'),
+                    xsd.String()),
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_2'),
+                    xsd.ComplexType(
+                        xsd.Sequence([
+                            xsd.Any()
+                        ])
+                    )
+                )
+            ])
+        ))
+    assert custom_type.signature() == (
+        '({item_1: xsd:string} | {item_2: {_value_1: ANY}})')
+
+
+def test_signature_complex_type_sequence_with_anys():
+    custom_type = xsd.Element(
+        etree.QName('http://tests.python-zeep.org/', 'authentication'),
+        xsd.ComplexType(
+            xsd.Choice([
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_1'),
+                    xsd.String()),
+                xsd.Element(
+                    etree.QName('http://tests.python-zeep.org/', 'item_2'),
+                    xsd.ComplexType(
+                        xsd.Sequence([
+                            xsd.Any(),
+                            xsd.Any(),
+                        ])
+                    )
+                )
+            ])
+        ))
+    assert custom_type.signature() == (
+        '({item_1: xsd:string} | {item_2: {_value_1: ANY, _value_2: ANY}})')
diff --git a/tests/test_xsd_simple_types.py b/tests/test_xsd_simple_types.py
new file mode 100644
index 0000000..fe22a4c
--- /dev/null
+++ b/tests/test_xsd_simple_types.py
@@ -0,0 +1,193 @@
+from lxml import etree
+
+from tests.utils import assert_nodes_equal, load_xml
+from zeep import xsd
+
+
+def test_simple_type():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="item">
+            <complexType>
+              <sequence>
+                <element name="something" type="long"/>
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+    item_cls = schema.get_element('{http://tests.python-zeep.org/}item')
+    item = item_cls(something=12345678901234567890)
+
+    node = etree.Element('document')
+    item_cls.render(node, item)
+    expected = """
+        <document>
+          <ns0:item xmlns:ns0="http://tests.python-zeep.org/">
+            <ns0:something>12345678901234567890</ns0:something>
+          </ns0:item>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    item = item_cls.parse(node.getchildren()[0], schema)
+    assert item.something == 12345678901234567890
+
+
+def test_simple_type_optional():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="item">
+            <complexType>
+              <sequence>
+                <element name="something" type="long" minOccurs="0"/>
+              </sequence>
+            </complexType>
+          </element>
+        </schema>
+    """))
+
+    item_cls = schema.get_element('{http://tests.python-zeep.org/}item')
+    item = item_cls()
+    assert item.something is None
+
+    node = etree.Element('document')
+    item_cls.render(node, item)
+    expected = """
+        <document>
+          <ns0:item xmlns:ns0="http://tests.python-zeep.org/"/>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+    item = item_cls.parse(node.getchildren()[0], schema)
+    assert item.something is None
+
+
+def test_restriction_global():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <simpleType name="foo">
+            <restriction base="integer">
+              <minInclusive value="0"/>
+              <maxInclusive value="100"/>
+            </restriction>
+          </simpleType>
+        </schema>
+    """))
+
+    type_cls = schema.get_type('{http://tests.python-zeep.org/}foo')
+    assert type_cls.qname.text == '{http://tests.python-zeep.org/}foo'
+
+
+def test_restriction_anon():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+          <element name="something">
+            <simpleType>
+              <restriction base="integer">
+                <minInclusive value="0"/>
+                <maxInclusive value="100"/>
+              </restriction>
+            </simpleType>
+          </element>
+        </schema>
+    """))
+
+    element_cls = schema.get_element('{http://tests.python-zeep.org/}something')
+    assert element_cls.type.qname == etree.QName(
+        '{http://tests.python-zeep.org/}something')
+
+    obj = element_cls(75)
+
+    node = etree.Element('document')
+    element_cls.render(node, obj)
+    expected = """
+        <document>
+            <ns0:something xmlns:ns0="http://tests.python-zeep.org/">75</ns0:something>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+def test_simple_type_list():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+
+          <simpleType name="values">
+            <list itemType="integer"/>
+          </simpleType>
+          <element name="something" type="tns:values"/>
+        </schema>
+    """))
+
+    element_cls = schema.get_element('{http://tests.python-zeep.org/}something')
+    obj = element_cls([1, 2, 3])
+    assert obj == [1, 2, 3]
+
+    node = etree.Element('document')
+    element_cls.render(node, obj)
+    expected = """
+        <document>
+            <ns0:something xmlns:ns0="http://tests.python-zeep.org/">1 2 3</ns0:something>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+
+
+def test_simple_type_list_custom_type():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"
+                xmlns:tns="http://tests.python-zeep.org/"
+                targetNamespace="http://tests.python-zeep.org/"
+                elementFormDefault="qualified">
+
+          <simpleType name="CountryNameType">
+            <list>
+              <simpleType>
+                <restriction base="string">
+                  <enumeration value="None"/>
+                  <enumeration value="AlternateName"/>
+                  <enumeration value="City"/>
+                  <enumeration value="Code"/>
+                  <enumeration value="Country"/>
+                </restriction>
+              </simpleType>
+            </list>
+          </simpleType>
+          <element name="something" type="tns:CountryNameType"/>
+        </schema>
+    """))
+
+    element_cls = schema.get_element('{http://tests.python-zeep.org/}something')
+    obj = element_cls(['Code', 'City'])
+    assert obj == ['Code', 'City']
+
+    node = etree.Element('document')
+    element_cls.render(node, obj)
+    expected = """
+        <document>
+            <ns0:something xmlns:ns0="http://tests.python-zeep.org/">Code City</ns0:something>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
diff --git a/tests/test_xsd_types.py b/tests/test_xsd_types.py
new file mode 100644
index 0000000..5e902fa
--- /dev/null
+++ b/tests/test_xsd_types.py
@@ -0,0 +1,80 @@
+import pytest
+import six
+from lxml import etree
+
+from zeep.xsd import types
+
+
+def test_base_type():
+    # Basically just for coverage... ;-)
+    base = types.Type()
+    with pytest.raises(NotImplementedError):
+        base.accept('x')
+
+    with pytest.raises(NotImplementedError):
+        base.parse_xmlelement(None)
+
+    with pytest.raises(NotImplementedError):
+        base.parsexml(None)
+
+    with pytest.raises(NotImplementedError):
+        base.render(None, None)
+
+    with pytest.raises(NotImplementedError):
+        base.resolve()
+
+    base.signature() == ''
+
+
+def test_simpletype_eq():
+    type_1 = types.SimpleType()
+    type_2 = types.SimpleType()
+
+    assert type_1 == type_2
+
+
+def test_simpletype_parse():
+    node = etree.Element('foobar')
+    item = types.SimpleType()
+
+    assert item.parse_xmlelement(node) is None
+
+
+def test_simpletype_xmlvalue():
+    item = types.SimpleType()
+
+    with pytest.raises(NotImplementedError):
+        item.xmlvalue(None)
+
+
+def test_simpletype_pythonvalue():
+    item = types.SimpleType()
+
+    with pytest.raises(NotImplementedError):
+        item.pythonvalue(None)
+
+
+def test_simpletype_call_wrong_arg_count():
+    item = types.SimpleType()
+
+    with pytest.raises(TypeError):
+        item('foo', 'bar')
+
+
+def test_simpletype_call_wrong_kwarg():
+    item = types.SimpleType()
+
+    with pytest.raises(TypeError):
+        item(uhhh='x')
+
+
+def test_simpletype_str():
+    item = types.SimpleType()
+    item.name = u'foobar'
+    assert six.text_type(item) == 'SimpleType(value)'
+
+
+def test_complextype_parse_xmlelement_no_childs():
+    xmlelement = etree.Element('foobar')
+    item = types.ComplexType()
+    assert item.parse_xmlelement(xmlelement, None) is None
diff --git a/tests/test_xsd_union.py b/tests/test_xsd_union.py
new file mode 100644
index 0000000..ad56f93
--- /dev/null
+++ b/tests/test_xsd_union.py
@@ -0,0 +1,91 @@
+import datetime
+import io
+
+from lxml import etree
+
+from tests.utils import DummyTransport, assert_nodes_equal, load_xml, render_node
+from zeep import xsd
+
+
+def test_union_same_types():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+
+
+          <xsd:simpleType name="MMYY">
+            <xsd:restriction base="xsd:int"/>
+          </xsd:simpleType>
+
+          <xsd:simpleType name="MMYYYY">
+            <xsd:restriction base="xsd:int"/>
+          </xsd:simpleType>
+
+          <xsd:simpleType name="Date">
+            <xsd:union memberTypes="MMYY MMYYYY"/>
+          </xsd:simpleType>
+          <xsd:element name="item" type="tns:Date"/>
+        </xsd:schema>
+    """))
+
+    elm = schema.get_element('ns0:item')
+    node = render_node(elm, '102018')
+    expected = """
+        <document>
+          <ns0:item xmlns:ns0="http://tests.python-zeep.org/">102018</ns0:item>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    value = elm.parse(node.getchildren()[0], schema)
+    assert value == 102018
+
+
+def test_union_mixed():
+    schema = xsd.Schema(load_xml("""
+        <?xml version="1.0"?>
+        <xsd:schema
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:tns="http://tests.python-zeep.org/"
+            targetNamespace="http://tests.python-zeep.org/"
+            elementFormDefault="qualified">
+          <xsd:element name="item" type="tns:Date"/>
+          <xsd:simpleType name="Date">
+            <xsd:union memberTypes="xsd:date xsd:gYear xsd:gYearMonth MMYY MMYYYY"/>
+          </xsd:simpleType>
+          <xsd:simpleType name="MMYY">
+            <xsd:restriction base="xsd:string">
+              <xsd:pattern value="(0[123456789]|1[012]){1}\d{2}"/>
+            </xsd:restriction>
+          </xsd:simpleType>
+          <xsd:simpleType name="MMYYYY">
+            <xsd:restriction base="xsd:string">
+              <xsd:pattern value="(0[123456789]|1[012]){1}\d{4}"/>
+            </xsd:restriction>
+          </xsd:simpleType>
+        </xsd:schema>
+    """))
+
+    elm = schema.get_element('ns0:item')
+    node = render_node(elm, '102018')
+    expected = """
+        <document>
+          <ns0:item xmlns:ns0="http://tests.python-zeep.org/">102018</ns0:item>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    value = elm.parse(node.getchildren()[0], schema)
+    assert value == '102018'
+
+    node = render_node(elm, '2018')
+    expected = """
+        <document>
+          <ns0:item xmlns:ns0="http://tests.python-zeep.org/">2018</ns0:item>
+        </document>
+    """
+    assert_nodes_equal(expected, node)
+    value = elm.parse(node.getchildren()[0], schema)
+    assert value == '2018'
diff --git a/tests/test_xsd_valueobjects.py b/tests/test_xsd_valueobjects.py
new file mode 100644
index 0000000..f9c6eaa
--- /dev/null
+++ b/tests/test_xsd_valueobjects.py
@@ -0,0 +1,403 @@
+import pytest
+import six
+
+from zeep import xsd
+from zeep.xsd import valueobjects
+
+
+def test_simple_args():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Element('item_1', xsd.String()),
+            xsd.Element('item_2', xsd.String())
+        ]))
+    args = tuple(['value-1', 'value-2'])
+    kwargs = {}
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        'item_1': 'value-1',
+        'item_2': 'value-2',
+    }
+
+
+def test_simple_args_attributes():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Element('item_1', xsd.String()),
+            xsd.Element('item_2', xsd.String())
+        ]),
+        [
+            xsd.Attribute('attr_1', xsd.String())
+        ]
+    )
+    args = tuple(['value-1', 'value-2', 'bla'])
+    kwargs = {}
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        'item_1': 'value-1',
+        'item_2': 'value-2',
+        'attr_1': 'bla',
+    }
+
+
+def test_simple_args_attributes_as_kwargs():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Element('item_1', xsd.String()),
+            xsd.Element('item_2', xsd.String())
+        ]),
+        [
+            xsd.Attribute('attr_1', xsd.String())
+        ]
+    )
+    args = tuple(['value-1', 'value-2'])
+    kwargs = {'attr_1': 'bla'}
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        'item_1': 'value-1',
+        'item_2': 'value-2',
+        'attr_1': 'bla',
+    }
+
+
+def test_simple_args_too_many():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Element('item_1', xsd.String()),
+            xsd.Element('item_2', xsd.String())
+        ]))
+    args = tuple(['value-1', 'value-2', 'value-3'])
+    kwargs = {}
+
+    try:
+        valueobjects._process_signature(xsd_type, args, kwargs)
+    except TypeError as exc:
+        assert six.text_type(exc) == (
+            '__init__() takes at most 2 positional arguments (3 given)')
+    else:
+        assert False, "TypeError not raised"
+
+
+def test_simple_args_too_few():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Element('item_1', xsd.String()),
+            xsd.Element('item_2', xsd.String())
+        ]))
+    args = tuple(['value-1'])
+    kwargs = {}
+    valueobjects._process_signature(xsd_type, args, kwargs)
+
+
+def test_simple_kwargs():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Element('item_1', xsd.String()),
+            xsd.Element('item_2', xsd.String())
+        ]))
+    args = tuple([])
+    kwargs = {'item_1': 'value-1', 'item_2': 'value-2'}
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        'item_1': 'value-1',
+        'item_2': 'value-2',
+    }
+
+
+def test_simple_mixed():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Element('item_1', xsd.String()),
+            xsd.Element('item_2', xsd.String())
+        ]))
+    args = tuple(['value-1'])
+    kwargs = {'item_2': 'value-2'}
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        'item_1': 'value-1',
+        'item_2': 'value-2',
+    }
+
+
+def test_choice():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Element('item_1', xsd.String()),
+                xsd.Element('item_2', xsd.String())
+            ])
+        ])
+    )
+    args = tuple([])
+    kwargs = {'item_2': 'value-2'}
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {'item_1': None, 'item_2': 'value-2'}
+
+
+def test_choice_max_occurs_simple_interface():
+    fields = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Element('item_1', xsd.String()),
+                xsd.Element('item_2', xsd.String())
+            ], max_occurs=2)
+        ])
+    )
+    args = tuple([])
+    kwargs = {
+        '_value_1': [{'item_1': 'foo'}, {'item_2': 'bar'}]
+    }
+    result = valueobjects._process_signature(fields, args, kwargs)
+    assert result == {
+        '_value_1': [
+            {'item_1': 'foo'},
+            {'item_2': 'bar'},
+        ]
+    }
+
+
+def test_choice_max_occurs():
+    fields = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Element('item_1', xsd.String()),
+                xsd.Element('item_2', xsd.String())
+            ], max_occurs=3)
+        ])
+    )
+    args = tuple([])
+    kwargs = {
+        '_value_1': [
+            {'item_1': 'foo'}, {'item_2': 'bar'}, {'item_1': 'bla'}
+        ]
+    }
+    result = valueobjects._process_signature(fields, args, kwargs)
+    assert result == {
+        '_value_1': [
+            {'item_1': 'foo'},
+            {'item_2': 'bar'},
+            {'item_1': 'bla'},
+        ]
+    }
+
+
+def test_choice_max_occurs_on_choice():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Element('item_1', xsd.String(), max_occurs=2),
+                xsd.Element('item_2', xsd.String())
+            ], max_occurs=2)
+        ])
+    )
+    args = tuple([])
+    kwargs = {
+        '_value_1': [
+            {'item_1': ['foo', 'bar']},
+            {'item_2': 'bla'},
+        ]
+    }
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        '_value_1': [
+            {'item_1': ['foo', 'bar']},
+            {'item_2': 'bla'}
+        ]
+    }
+
+
+def test_choice_mixed():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Element('item_1', xsd.String()),
+                xsd.Element('item_2', xsd.String()),
+            ]),
+            xsd.Element('item_2', xsd.String())
+        ])
+    )
+    expected = '({item_1: xsd:string} | {item_2: xsd:string}), item_2__1: xsd:string'
+    assert xsd_type.signature() == expected
+
+    args = tuple([])
+    kwargs = {'item_1': 'value-1', 'item_2__1': 'value-2'}
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        'item_1': 'value-1',
+        'item_2': None,
+        'item_2__1': 'value-2',
+    }
+
+
+def test_choice_sequences_simple():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Sequence([
+                    xsd.Element('item_1', xsd.String()),
+                    xsd.Element('item_2', xsd.String())
+                ]),
+                xsd.Sequence([
+                    xsd.Element('item_3', xsd.String()),
+                    xsd.Element('item_4', xsd.String())
+                ]),
+            ])
+        ])
+    )
+    args = tuple([])
+    kwargs = {'item_1': 'value-1', 'item_2': 'value-2'}
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        'item_1': 'value-1',
+        'item_2': 'value-2',
+        'item_3': None,
+        'item_4': None,
+    }
+
+
+def test_choice_sequences_no_match():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Sequence([
+                    xsd.Element('item_1', xsd.String()),
+                    xsd.Element('item_2', xsd.String())
+                ]),
+                xsd.Sequence([
+                    xsd.Element('item_3', xsd.String()),
+                    xsd.Element('item_4', xsd.String())
+                ]),
+            ])
+        ])
+    )
+    args = tuple([])
+    with pytest.raises(TypeError):
+        kwargs = {'item_1': 'value-1', 'item_3': 'value-3'}
+        valueobjects._process_signature(xsd_type, args, kwargs)
+
+
+def test_choice_sequences_no_match_last():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Sequence([
+                    xsd.Element('item_1', xsd.String()),
+                    xsd.Element('item_2', xsd.String())
+                ]),
+                xsd.Sequence([
+                    xsd.Element('item_3', xsd.String()),
+                    xsd.Element('item_4', xsd.String())
+                ]),
+            ])
+        ])
+    )
+    args = tuple([])
+    with pytest.raises(TypeError):
+        kwargs = {'item_2': 'value-2', 'item_4': 'value-4'}
+        valueobjects._process_signature(xsd_type, args, kwargs)
+
+
+def test_choice_sequences_no_match_nested():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Sequence([
+                    xsd.Element('item_1', xsd.String()),
+                    xsd.Element('item_2', xsd.String())
+                ]),
+            ])
+        ])
+    )
+    args = tuple([])
+    kwargs = {'item_1': 'value-1'}
+    value = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert value == {
+        'item_1': 'value-1',
+        'item_2': None,
+    }
+
+
+def test_choice_sequences_optional_elms():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Sequence([
+                    xsd.Element('item_1', xsd.String()),
+                    xsd.Element('item_2', xsd.String(), min_occurs=0)
+                ]),
+                xsd.Sequence([
+                    xsd.Element('item_1', xsd.String()),
+                    xsd.Element('item_2', xsd.String()),
+                    xsd.Element('item_3', xsd.String())
+                ]),
+            ])
+        ])
+    )
+    args = tuple([])
+    kwargs = {'item_1': 'value-1'}
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        'item_1': 'value-1',
+        'item_2': None,
+        'item_3': None,
+    }
+
+
+def test_choice_sequences_max_occur():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Sequence([
+                    xsd.Element('item_1', xsd.String()),
+                    xsd.Element('item_2', xsd.String())
+                ]),
+                xsd.Sequence([
+                    xsd.Element('item_2', xsd.String()),
+                    xsd.Element('item_3', xsd.String()),
+                ]),
+            ], max_occurs=2)
+        ]),
+    )
+    args = tuple([])
+    kwargs = {
+        '_value_1': [
+            {'item_1': 'value-1', 'item_2': 'value-2'},
+            {'item_2': 'value-2', 'item_3': 'value-3'},
+        ]
+    }
+
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        '_value_1': [
+            {'item_1': 'value-1', 'item_2': 'value-2'},
+            {'item_2': 'value-2', 'item_3': 'value-3'},
+        ]
+    }
+
+
+def test_choice_sequences_init_dict():
+    xsd_type = xsd.ComplexType(
+        xsd.Sequence([
+            xsd.Choice([
+                xsd.Sequence([
+                    xsd.Element('item_1', xsd.String()),
+                    xsd.Element('item_2', xsd.String())
+                ]),
+                xsd.Sequence([
+                    xsd.Element('item_2', xsd.String()),
+                    xsd.Element('item_3', xsd.String()),
+                ]),
+            ], max_occurs=2)
+        ]),
+    )
+    args = tuple([])
+    kwargs = {
+        '_value_1': {'item_1': 'value-1', 'item_2': 'value-2'},
+    }
+
+    result = valueobjects._process_signature(xsd_type, args, kwargs)
+    assert result == {
+        '_value_1': [
+            {'item_1': 'value-1', 'item_2': 'value-2'}
+        ]
+    }
diff --git a/tests/wsdl_files/soap-enc.xsd b/tests/wsdl_files/soap-enc.xsd
new file mode 100644
index 0000000..de4a44a
--- /dev/null
+++ b/tests/wsdl_files/soap-enc.xsd
@@ -0,0 +1,535 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+
+<!-- Schema for the SOAP/1.1 encoding
+
+Portions © 2001 DevelopMentor. 
+© 2001 W3C (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved.  
+ 
+This document is governed by the W3C Software License [1] as described in the FAQ [2].
+[1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
+[2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD 
+By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
+
+Permission to use, copy, modify, and distribute this software and its documentation, with or without modification,  for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make:
+
+1.  The full text of this NOTICE in a location viewable to users of the redistributed or derivative work. 
+
+2.  Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, a short notice of the following form (hypertext is preferred, text is permitted) should be used within the body of any redistributed or derivative code: "Copyright © 2001 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/" 
+
+3.  Notice of any changes or modifications to the W3C files, including the date changes were made. (We recommend you provide URIs to the location from which the code is derived.)   
+
+Original W3C files; http://www.w3.org/2001/06/soap-encoding
+Changes made: 
+     - reverted namespace to http://schemas.xmlsoap.org/soap/encoding/
+     - reverted root to only allow 0 and 1 as lexical values
+	 - removed default value from root attribute declaration
+
+THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+
+COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
+
+The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software without specific, written prior permission. Title to copyright in this software and any associated documentation will at all times remain with copyright holders.
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:tns="http://schemas.xmlsoap.org/soap/encoding/"
+           targetNamespace="http://schemas.xmlsoap.org/soap/encoding/" >
+        
+ <xs:attribute name="root" >
+   <xs:annotation>
+     <xs:documentation>
+	   'root' can be used to distinguish serialization roots from other
+       elements that are present in a serialization but are not roots of
+       a serialized value graph 
+	 </xs:documentation>
+   </xs:annotation>
+   <xs:simpleType>
+     <xs:restriction base='xs:boolean'>
+	   <xs:pattern value='0|1' />
+	 </xs:restriction>
+   </xs:simpleType>
+ </xs:attribute>
+
+  <xs:attributeGroup name="commonAttributes" >
+    <xs:annotation>
+	  <xs:documentation>
+	    Attributes common to all elements that function as accessors or 
+        represent independent (multi-ref) values.  The href attribute is
+        intended to be used in a manner like CONREF.  That is, the element
+        content should be empty iff the href attribute appears
+	  </xs:documentation>
+	</xs:annotation>
+    <xs:attribute name="id" type="xs:ID" />
+    <xs:attribute name="href" type="xs:anyURI" />
+    <xs:anyAttribute namespace="##other" processContents="lax" />
+  </xs:attributeGroup>
+
+  <!-- Global Attributes.  The following attributes are intended to be usable via qualified attribute names on any complex type referencing them. -->
+       
+  <!-- Array attributes. Needed to give the type and dimensions of an array's contents, and the offset for partially-transmitted arrays. -->
+   
+  <xs:simpleType name="arrayCoordinate" >
+    <xs:restriction base="xs:string" />
+  </xs:simpleType>
+          
+  <xs:attribute name="arrayType" type="xs:string" />
+  <xs:attribute name="offset" type="tns:arrayCoordinate" />
+  
+  <xs:attributeGroup name="arrayAttributes" >
+    <xs:attribute ref="tns:arrayType" />
+    <xs:attribute ref="tns:offset" />
+  </xs:attributeGroup>    
+  
+  <xs:attribute name="position" type="tns:arrayCoordinate" /> 
+  
+  <xs:attributeGroup name="arrayMemberAttributes" >
+    <xs:attribute ref="tns:position" />
+  </xs:attributeGroup>    
+
+  <xs:group name="Array" >
+    <xs:sequence>
+      <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
+	</xs:sequence>
+  </xs:group>
+
+  <xs:element name="Array" type="tns:Array" />
+  <xs:complexType name="Array" >
+    <xs:annotation>
+	  <xs:documentation>
+	   'Array' is a complex type for accessors identified by position 
+	  </xs:documentation>
+	</xs:annotation>
+    <xs:group ref="tns:Array" minOccurs="0" />
+    <xs:attributeGroup ref="tns:arrayAttributes" />
+    <xs:attributeGroup ref="tns:commonAttributes" />
+  </xs:complexType> 
+
+  <!-- 'Struct' is a complex type for accessors identified by name. 
+       Constraint: No element may be have the same name as any other,
+       nor may any element have a maxOccurs > 1. -->
+   
+  <xs:element name="Struct" type="tns:Struct" />
+
+  <xs:group name="Struct" >
+    <xs:sequence>
+      <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
+	</xs:sequence>
+  </xs:group>
+
+  <xs:complexType name="Struct" >
+    <xs:group ref="tns:Struct" minOccurs="0" />
+    <xs:attributeGroup ref="tns:commonAttributes"/>
+  </xs:complexType> 
+
+  <!-- 'Base64' can be used to serialize binary data using base64 encoding
+       as defined in RFC2045 but without the MIME line length limitation. -->
+
+  <xs:simpleType name="base64" >
+    <xs:restriction base="xs:base64Binary" />
+  </xs:simpleType>
+
+ <!-- Element declarations corresponding to each of the simple types in the 
+      XML Schemas Specification. -->
+
+  <xs:element name="duration" type="tns:duration" />
+  <xs:complexType name="duration" >
+    <xs:simpleContent>
+      <xs:extension base="xs:duration" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="dateTime" type="tns:dateTime" />
+  <xs:complexType name="dateTime" >
+    <xs:simpleContent>
+      <xs:extension base="xs:dateTime" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+
+
+  <xs:element name="NOTATION" type="tns:NOTATION" />
+  <xs:complexType name="NOTATION" >
+    <xs:simpleContent>
+      <xs:extension base="xs:QName" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+  
+
+  <xs:element name="time" type="tns:time" />
+  <xs:complexType name="time" >
+    <xs:simpleContent>
+      <xs:extension base="xs:time" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="date" type="tns:date" />
+  <xs:complexType name="date" >
+    <xs:simpleContent>
+      <xs:extension base="xs:date" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="gYearMonth" type="tns:gYearMonth" />
+  <xs:complexType name="gYearMonth" >
+    <xs:simpleContent>
+      <xs:extension base="xs:gYearMonth" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="gYear" type="tns:gYear" />
+  <xs:complexType name="gYear" >
+    <xs:simpleContent>
+      <xs:extension base="xs:gYear" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="gMonthDay" type="tns:gMonthDay" />
+  <xs:complexType name="gMonthDay" >
+    <xs:simpleContent>
+      <xs:extension base="xs:gMonthDay" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="gDay" type="tns:gDay" />
+  <xs:complexType name="gDay" >
+    <xs:simpleContent>
+      <xs:extension base="xs:gDay" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="gMonth" type="tns:gMonth" />
+  <xs:complexType name="gMonth" >
+    <xs:simpleContent>
+      <xs:extension base="xs:gMonth" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+  
+  <xs:element name="boolean" type="tns:boolean" />
+  <xs:complexType name="boolean" >
+    <xs:simpleContent>
+      <xs:extension base="xs:boolean" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="base64Binary" type="tns:base64Binary" />
+  <xs:complexType name="base64Binary" >
+    <xs:simpleContent>
+      <xs:extension base="xs:base64Binary" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="hexBinary" type="tns:hexBinary" />
+  <xs:complexType name="hexBinary" >
+    <xs:simpleContent>
+     <xs:extension base="xs:hexBinary" >
+       <xs:attributeGroup ref="tns:commonAttributes" />
+     </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="float" type="tns:float" />
+  <xs:complexType name="float" >
+    <xs:simpleContent>
+      <xs:extension base="xs:float" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="double" type="tns:double" />
+  <xs:complexType name="double" >
+    <xs:simpleContent>
+      <xs:extension base="xs:double" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="anyURI" type="tns:anyURI" />
+  <xs:complexType name="anyURI" >
+    <xs:simpleContent>
+      <xs:extension base="xs:anyURI" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="QName" type="tns:QName" />
+  <xs:complexType name="QName" >
+    <xs:simpleContent>
+      <xs:extension base="xs:QName" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  
+  <xs:element name="string" type="tns:string" />
+  <xs:complexType name="string" >
+    <xs:simpleContent>
+      <xs:extension base="xs:string" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="normalizedString" type="tns:normalizedString" />
+  <xs:complexType name="normalizedString" >
+    <xs:simpleContent>
+      <xs:extension base="xs:normalizedString" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="token" type="tns:token" />
+  <xs:complexType name="token" >
+    <xs:simpleContent>
+      <xs:extension base="xs:token" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="language" type="tns:language" />
+  <xs:complexType name="language" >
+    <xs:simpleContent>
+      <xs:extension base="xs:language" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="Name" type="tns:Name" />
+  <xs:complexType name="Name" >
+    <xs:simpleContent>
+      <xs:extension base="xs:Name" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="NMTOKEN" type="tns:NMTOKEN" />
+  <xs:complexType name="NMTOKEN" >
+    <xs:simpleContent>
+      <xs:extension base="xs:NMTOKEN" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="NCName" type="tns:NCName" />
+  <xs:complexType name="NCName" >
+    <xs:simpleContent>
+      <xs:extension base="xs:NCName" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="NMTOKENS" type="tns:NMTOKENS" />
+  <xs:complexType name="NMTOKENS" >
+    <xs:simpleContent>
+      <xs:extension base="xs:NMTOKENS" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="ID" type="tns:ID" />
+  <xs:complexType name="ID" >
+    <xs:simpleContent>
+      <xs:extension base="xs:ID" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="IDREF" type="tns:IDREF" />
+  <xs:complexType name="IDREF" >
+    <xs:simpleContent>
+      <xs:extension base="xs:IDREF" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="ENTITY" type="tns:ENTITY" />
+  <xs:complexType name="ENTITY" >
+    <xs:simpleContent>
+      <xs:extension base="xs:ENTITY" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="IDREFS" type="tns:IDREFS" />
+  <xs:complexType name="IDREFS" >
+    <xs:simpleContent>
+      <xs:extension base="xs:IDREFS" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="ENTITIES" type="tns:ENTITIES" />
+  <xs:complexType name="ENTITIES" >
+    <xs:simpleContent>
+      <xs:extension base="xs:ENTITIES" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="decimal" type="tns:decimal" />
+  <xs:complexType name="decimal" >
+    <xs:simpleContent>
+      <xs:extension base="xs:decimal" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="integer" type="tns:integer" />
+  <xs:complexType name="integer" >
+    <xs:simpleContent>
+      <xs:extension base="xs:integer" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="nonPositiveInteger" type="tns:nonPositiveInteger" />
+  <xs:complexType name="nonPositiveInteger" >
+    <xs:simpleContent>
+      <xs:extension base="xs:nonPositiveInteger" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="negativeInteger" type="tns:negativeInteger" />
+  <xs:complexType name="negativeInteger" >
+    <xs:simpleContent>
+      <xs:extension base="xs:negativeInteger" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="long" type="tns:long" />
+  <xs:complexType name="long" >
+    <xs:simpleContent>
+      <xs:extension base="xs:long" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="int" type="tns:int" />
+  <xs:complexType name="int" >
+    <xs:simpleContent>
+      <xs:extension base="xs:int" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="short" type="tns:short" />
+  <xs:complexType name="short" >
+    <xs:simpleContent>
+      <xs:extension base="xs:short" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="byte" type="tns:byte" />
+  <xs:complexType name="byte" >
+    <xs:simpleContent>
+      <xs:extension base="xs:byte" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="nonNegativeInteger" type="tns:nonNegativeInteger" />
+  <xs:complexType name="nonNegativeInteger" >
+    <xs:simpleContent>
+      <xs:extension base="xs:nonNegativeInteger" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="unsignedLong" type="tns:unsignedLong" />
+  <xs:complexType name="unsignedLong" >
+    <xs:simpleContent>
+      <xs:extension base="xs:unsignedLong" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="unsignedInt" type="tns:unsignedInt" />
+  <xs:complexType name="unsignedInt" >
+    <xs:simpleContent>
+      <xs:extension base="xs:unsignedInt" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="unsignedShort" type="tns:unsignedShort" />
+  <xs:complexType name="unsignedShort" >
+    <xs:simpleContent>
+      <xs:extension base="xs:unsignedShort" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="unsignedByte" type="tns:unsignedByte" />
+  <xs:complexType name="unsignedByte" >
+    <xs:simpleContent>
+      <xs:extension base="xs:unsignedByte" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="positiveInteger" type="tns:positiveInteger" />
+  <xs:complexType name="positiveInteger" >
+    <xs:simpleContent>
+      <xs:extension base="xs:positiveInteger" >
+        <xs:attributeGroup ref="tns:commonAttributes" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:element name="anyType" />
+</xs:schema>
diff --git a/tests/wsdl_files/soap_import_2.wsdl b/tests/wsdl_files/soap_import_2.wsdl
new file mode 100644
index 0000000..be02d41
--- /dev/null
+++ b/tests/wsdl_files/soap_import_2.wsdl
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<definitions 
+    xmlns:tns="http://example.com/stockquote.wsdl" 
+    xmlns:xsd1="http://example.com/stockquote.xsd" 
+    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
+    xmlns="http://schemas.xmlsoap.org/wsdl/"
+    name="StockQuote" 
+    targetNamespace="http://example.com/stockquote.wsdl">
+  <types>
+    <schema xmlns="http://www.w3.org/2001/XMLSchema" 
+            targetNamespace="http://test.python-zeep.org/imports"
+            xmlns:tns="http://test.python-zeep.org/imports">
+      <import schemaLocation="test_import_2.xsd" namespace="http://example.com/stockquote.xsd"/>
+    </schema>
+    <schema xmlns="http://www.w3.org/2001/XMLSchema" 
+            targetNamespace="http://test.python-zeep.org/something"
+            xmlns:tns="http://test.python-zeep.org/something">
+      <import namespace="http://schemas.xmlsoap.org/soap/encoding/" 
+              schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/>
+    </schema>
+  </types>
+  <message name="GetLastTradePriceInput">
+    <part name="body" element="xsd1:TradePriceRequest"/>
+  </message>
+  <message name="GetLastTradePriceOutput">
+    <part name="body" element="xsd1:TradePrice"/>
+  </message>
+  <message name="FaultMessageMsg1">
+    <part name="fault1" element="xsd1:Fault1"/>
+  </message>
+  <message name="FaultMessageMsg2">
+    <part name="fault2" element="xsd1:Fault2"/>
+  </message>
+  <portType name="StockQuotePortType">
+    <operation name="GetLastTradePrice">
+      <input message="tns:GetLastTradePriceInput"/>
+      <output message="tns:GetLastTradePriceOutput"/>
+      <fault message="tns:FaultMessageMsg1" name="fault1"/>
+      <fault message="tns:FaultMessageMsg2" name="fault2"/>
+    </operation>
+  </portType>
+</definitions>
diff --git a/tests/wsdl_files/soap_import_main.wsdl b/tests/wsdl_files/soap_import_main.wsdl
new file mode 100644
index 0000000..976c4cf
--- /dev/null
+++ b/tests/wsdl_files/soap_import_main.wsdl
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<definitions 
+    xmlns:tns="http://example.com/stockquote.wsdl" 
+    xmlns:xsd1="http://example.com/stockquote.xsd" 
+    xmlns:sub="http://test.python-zeep.org/sub"
+    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
+    xmlns="http://schemas.xmlsoap.org/wsdl/"
+    name="StockQuote" 
+    targetNamespace="http://example.com/stockquote.wsdl">
+  <import namespace="http://test.python-zeep.org/sub" location="soap_import_2.wsdl"/>
+
+  <types/>
+  <binding name="StockQuoteBinding" type="tns:StockQuotePortType">
+    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <operation name="GetLastTradePrice">
+      <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
+      <input>
+        <soap:body use="literal"/>
+      </input>
+      <output>
+        <soap:body use="literal"/>
+      </output>
+      <fault name="fault1">
+        <soap:fault name="fault1" use="literal"/>
+      </fault>
+      <fault name="fault2">
+        <soap:fault name="fault2" use="literal"/>
+      </fault>
+    </operation>
+  </binding>
+  <service name="StockQuoteService">
+    <documentation>My first service</documentation>
+    <port name="StockQuotePort" binding="tns:StockQuoteBinding">
+      <soap:address location="http://example.com/stockquote"/>
+    </port>
+  </service>
+</definitions>
+
diff --git a/tests/wsdl_files/soap_transport_err.wsdl b/tests/wsdl_files/soap_transport_err.wsdl
new file mode 100644
index 0000000..980f632
--- /dev/null
+++ b/tests/wsdl_files/soap_transport_err.wsdl
@@ -0,0 +1,138 @@
+<?xml version="1.0"?>
+<definitions 
+    xmlns:tns="http://example.com/stockquote.wsdl" 
+    xmlns:xsd1="http://example.com/stockquote.xsd" 
+    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
+    xmlns="http://schemas.xmlsoap.org/wsdl/"
+    name="StockQuote" 
+    targetNamespace="http://example.com/stockquote.wsdl">
+  <types>
+    <schema xmlns="http://www.w3.org/2001/XMLSchema" 
+            targetNamespace="http://example.com/stockquote.xsd"
+            xmlns:tns="http://example.com/stockquote.xsd" >
+      <complexType name="Address">
+        <sequence>
+          <element minOccurs="0" maxOccurs="1" name="NameFirst" type="string"/>
+          <element minOccurs="0" maxOccurs="1" name="NameLast" type="string"/>
+          <element minOccurs="0" maxOccurs="1" name="Email" type="string"/>
+        </sequence>
+      </complexType>
+      <element name="Fault1">
+        <complexType>
+          <sequence>
+            <element name="message" type="string"/>
+          </sequence>
+        </complexType>
+      </element>
+      <element name="Fault2">
+        <complexType>
+          <sequence>
+            <element name="message" type="string"/>
+          </sequence>
+        </complexType>
+      </element>
+      <element name="TradePriceRequest">
+        <complexType>
+          <all>
+            <element name="tickerSymbol" type="string"/>
+            <element name="account" type="tns:account" minOccurs="0" />
+            <element ref="tns:country"/>
+          </all>
+        </complexType>
+      </element>
+      <element name="TradePrice">
+        <complexType>
+          <all>
+            <element name="price" type="float"/>
+          </all>
+        </complexType>
+      </element>
+      <complexType name="account">
+        <sequence>
+          <element name="id" type="int"/>
+          <element name="user" type="string"/>
+        </sequence>
+      </complexType>
+      <complexType name="country">
+          <sequence>
+            <element name="code" type="string"/>
+          </sequence>
+      </complexType>
+      <element name="country">
+        <complexType>
+          <sequence>
+            <element name="name" type="string"/>
+            <element name="code" type="string"/>
+          </sequence>
+        </complexType>
+      </element>
+    </schema>
+  </types>
+  <message name="GetLastTradePriceInput">
+    <part name="body" element="xsd1:TradePriceRequest"/>
+  </message>
+  <message name="GetLastTradePriceOutput">
+    <part name="body" element="xsd1:TradePrice"/>
+  </message>
+  <message name="FaultMessageMsg1">
+    <part name="fault1" element="xsd1:Fault1"/>
+  </message>
+  <message name="FaultMessageMsg2">
+    <part name="fault2" element="xsd1:Fault2"/>
+  </message>
+  <portType name="StockQuotePortType">
+    <operation name="GetLastTradePrice">
+      <input message="tns:GetLastTradePriceInput"/>
+      <output message="tns:GetLastTradePriceOutput"/>
+      <fault message="tns:FaultMessageMsg1" name="fault1"/>
+      <fault message="tns:FaultMessageMsg2" name="fault2"/>
+    </operation>
+  </portType>
+
+  <binding name="StockQuoteBinding" type="tns:StockQuotePortType">
+    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <operation name="GetLastTradePrice">
+      <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
+      <input>
+        <soap:body use="literal"/>
+      </input>
+      <output>
+        <soap:body use="literal"/>
+      </output>
+      <fault name="fault1">
+        <soap:fault name="fault1" use="literal"/>
+      </fault>
+      <fault name="fault2">
+        <soap:fault name="fault2" use="literal"/>
+      </fault>
+    </operation>
+  </binding>
+
+  <binding name="StockQuoteBinding" type="tns:StockQuotePortType">
+	  <soap:binding style="document" transport="http://schemas.microsoft.com/soap/tcp"/>
+    <operation name="GetLastTradePrice">
+      <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
+      <input>
+        <soap:body use="literal"/>
+      </input>
+      <output>
+        <soap:body use="literal"/>
+      </output>
+      <fault name="fault1">
+        <soap:fault name="fault1" use="literal"/>
+      </fault>
+      <fault name="fault2">
+        <soap:fault name="fault2" use="literal"/>
+      </fault>
+    </operation>
+  </binding>
+
+
+
+  <service name="StockQuoteService">
+    <documentation>My first service</documentation>
+    <port name="StockQuotePort" binding="tns:StockQuoteBinding">
+      <soap:address location="http://example.com/stockquote"/>
+    </port>
+  </service>
+</definitions>
diff --git a/tests/wsdl_files/test_import_2.xsd b/tests/wsdl_files/test_import_2.xsd
new file mode 100644
index 0000000..90194f6
--- /dev/null
+++ b/tests/wsdl_files/test_import_2.xsd
@@ -0,0 +1,60 @@
+<schema xmlns="http://www.w3.org/2001/XMLSchema" 
+        targetNamespace="http://example.com/stockquote.xsd"
+        xmlns:tns="http://example.com/stockquote.xsd" >
+  <complexType name="Address">
+    <sequence>
+      <element minOccurs="0" maxOccurs="1" name="NameFirst" type="string"/>
+      <element minOccurs="0" maxOccurs="1" name="NameLast" type="string"/>
+      <element minOccurs="0" maxOccurs="1" name="Email" type="string"/>
+    </sequence>
+  </complexType>
+  <element name="Fault1">
+    <complexType>
+      <sequence>
+        <element name="message" type="string"/>
+      </sequence>
+    </complexType>
+  </element>
+  <element name="Fault2">
+    <complexType>
+      <sequence>
+        <element name="message" type="string"/>
+      </sequence>
+    </complexType>
+  </element>
+  <element name="TradePriceRequest">
+    <complexType>
+      <all>
+        <element name="tickerSymbol" type="string"/>
+        <element name="account" type="tns:account" minOccurs="0" />
+        <element ref="tns:country"/>
+      </all>
+    </complexType>
+  </element>
+  <element name="TradePrice">
+    <complexType>
+      <all>
+        <element name="price" type="float"/>
+      </all>
+    </complexType>
+  </element>
+  <complexType name="account">
+    <sequence>
+      <element name="id" type="int"/>
+      <element name="user" type="string"/>
+    </sequence>
+  </complexType>
+  <complexType name="country">
+      <sequence>
+        <element name="code" type="string"/>
+      </sequence>
+  </complexType>
+  <element name="country">
+    <complexType>
+      <sequence>
+        <element name="name" type="string"/>
+        <element name="code" type="string"/>
+      </sequence>
+    </complexType>
+  </element>
+</schema>
diff --git a/tests/wsdl_files/xmldsig-core-schema.xsd b/tests/wsdl_files/xmldsig-core-schema.xsd
new file mode 100644
index 0000000..dd5254b
--- /dev/null
+++ b/tests/wsdl_files/xmldsig-core-schema.xsd
@@ -0,0 +1,309 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Schema for XML Signatures
+    http://www.w3.org/2000/09/xmldsig#
+    $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
+
+    Copyright 2001 The Internet Society and W3C (Massachusetts Institute
+    of Technology, Institut National de Recherche en Informatique et en
+    Automatique, Keio University). All Rights Reserved.
+    http://www.w3.org/Consortium/Legal/
+
+    This document is governed by the W3C Software License [1] as described
+    in the FAQ [2].
+
+    [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
+    [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
+-->
+
+
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+        xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+        targetNamespace="http://www.w3.org/2000/09/xmldsig#"
+        version="0.1" elementFormDefault="qualified"> 
+
+<!-- Basic Types Defined for Signatures -->
+
+<simpleType name="CryptoBinary">
+  <restriction base="base64Binary">
+  </restriction>
+</simpleType>
+
+<!-- Start Signature -->
+
+<element name="Signature" type="ds:SignatureType"/>
+<complexType name="SignatureType">
+  <sequence> 
+    <element ref="ds:SignedInfo"/> 
+    <element ref="ds:SignatureValue"/> 
+    <element ref="ds:KeyInfo" minOccurs="0"/> 
+    <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/> 
+  </sequence>  
+  <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+  <element name="SignatureValue" type="ds:SignatureValueType"/> 
+  <complexType name="SignatureValueType">
+    <simpleContent>
+      <extension base="base64Binary">
+        <attribute name="Id" type="ID" use="optional"/>
+      </extension>
+    </simpleContent>
+  </complexType>
+
+<!-- Start SignedInfo -->
+
+<element name="SignedInfo" type="ds:SignedInfoType"/>
+<complexType name="SignedInfoType">
+  <sequence> 
+    <element ref="ds:CanonicalizationMethod"/> 
+    <element ref="ds:SignatureMethod"/> 
+    <element ref="ds:Reference" maxOccurs="unbounded"/> 
+  </sequence>  
+  <attribute name="Id" type="ID" use="optional"/> 
+</complexType>
+
+  <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/> 
+  <complexType name="CanonicalizationMethodType" mixed="true">
+    <sequence>
+      <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
+      <!-- (0,unbounded) elements from (1,1) namespace -->
+    </sequence>
+    <attribute name="Algorithm" type="anyURI" use="required"/> 
+  </complexType>
+
+  <element name="SignatureMethod" type="ds:SignatureMethodType"/>
+  <complexType name="SignatureMethodType" mixed="true">
+    <sequence>
+      <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
+      <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+      <!-- (0,unbounded) elements from (1,1) external namespace -->
+    </sequence>
+    <attribute name="Algorithm" type="anyURI" use="required"/> 
+  </complexType>
+
+<!-- Start Reference -->
+
+<element name="Reference" type="ds:ReferenceType"/>
+<complexType name="ReferenceType">
+  <sequence> 
+    <element ref="ds:Transforms" minOccurs="0"/> 
+    <element ref="ds:DigestMethod"/> 
+    <element ref="ds:DigestValue"/> 
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/> 
+  <attribute name="URI" type="anyURI" use="optional"/> 
+  <attribute name="Type" type="anyURI" use="optional"/> 
+</complexType>
+
+  <element name="Transforms" type="ds:TransformsType"/>
+  <complexType name="TransformsType">
+    <sequence>
+      <element ref="ds:Transform" maxOccurs="unbounded"/>  
+    </sequence>
+  </complexType>
+
+  <element name="Transform" type="ds:TransformType"/>
+  <complexType name="TransformType" mixed="true">
+    <choice minOccurs="0" maxOccurs="unbounded"> 
+      <any namespace="##other" processContents="lax"/>
+      <!-- (1,1) elements from (0,unbounded) namespaces -->
+      <element name="XPath" type="string"/> 
+    </choice>
+    <attribute name="Algorithm" type="anyURI" use="required"/> 
+  </complexType>
+
+<!-- End Reference -->
+
+<element name="DigestMethod" type="ds:DigestMethodType"/>
+<complexType name="DigestMethodType" mixed="true"> 
+  <sequence>
+    <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+  </sequence>    
+  <attribute name="Algorithm" type="anyURI" use="required"/> 
+</complexType>
+
+<element name="DigestValue" type="ds:DigestValueType"/>
+<simpleType name="DigestValueType">
+  <restriction base="base64Binary"/>
+</simpleType>
+
+<!-- End SignedInfo -->
+
+<!-- Start KeyInfo -->
+
+<element name="KeyInfo" type="ds:KeyInfoType"/> 
+<complexType name="KeyInfoType" mixed="true">
+  <choice maxOccurs="unbounded">     
+    <element ref="ds:KeyName"/> 
+    <element ref="ds:KeyValue"/> 
+    <element ref="ds:RetrievalMethod"/> 
+    <element ref="ds:X509Data"/> 
+    <element ref="ds:PGPData"/> 
+    <element ref="ds:SPKIData"/>
+    <element ref="ds:MgmtData"/>
+    <any processContents="lax" namespace="##other"/>
+    <!-- (1,1) elements from (0,unbounded) namespaces -->
+  </choice>
+  <attribute name="Id" type="ID" use="optional"/> 
+</complexType>
+
+  <element name="KeyName" type="string"/>
+  <element name="MgmtData" type="string"/>
+
+  <element name="KeyValue" type="ds:KeyValueType"/> 
+  <complexType name="KeyValueType" mixed="true">
+   <choice>
+     <element ref="ds:DSAKeyValue"/>
+     <element ref="ds:RSAKeyValue"/>
+     <any namespace="##other" processContents="lax"/>
+   </choice>
+  </complexType>
+
+  <element name="RetrievalMethod" type="ds:RetrievalMethodType"/> 
+  <complexType name="RetrievalMethodType">
+    <sequence>
+      <element ref="ds:Transforms" minOccurs="0"/> 
+    </sequence>  
+    <attribute name="URI" type="anyURI"/>
+    <attribute name="Type" type="anyURI" use="optional"/>
+  </complexType>
+
+<!-- Start X509Data -->
+
+<element name="X509Data" type="ds:X509DataType"/> 
+<complexType name="X509DataType">
+  <sequence maxOccurs="unbounded">
+    <choice>
+      <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
+      <element name="X509SKI" type="base64Binary"/>
+      <element name="X509SubjectName" type="string"/>
+      <element name="X509Certificate" type="base64Binary"/>
+      <element name="X509CRL" type="base64Binary"/>
+      <any namespace="##other" processContents="lax"/>
+    </choice>
+  </sequence>
+</complexType>
+
+<complexType name="X509IssuerSerialType"> 
+  <sequence> 
+    <element name="X509IssuerName" type="string"/> 
+    <element name="X509SerialNumber" type="integer"/> 
+  </sequence>
+</complexType>
+
+<!-- End X509Data -->
+
+<!-- Begin PGPData -->
+
+<element name="PGPData" type="ds:PGPDataType"/> 
+<complexType name="PGPDataType"> 
+  <choice>
+    <sequence>
+      <element name="PGPKeyID" type="base64Binary"/> 
+      <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/> 
+      <any namespace="##other" processContents="lax" minOccurs="0"
+       maxOccurs="unbounded"/>
+    </sequence>
+    <sequence>
+      <element name="PGPKeyPacket" type="base64Binary"/> 
+      <any namespace="##other" processContents="lax" minOccurs="0"
+       maxOccurs="unbounded"/>
+    </sequence>
+  </choice>
+</complexType>
+
+<!-- End PGPData -->
+
+<!-- Begin SPKIData -->
+
+<element name="SPKIData" type="ds:SPKIDataType"/> 
+<complexType name="SPKIDataType">
+  <sequence maxOccurs="unbounded">
+    <element name="SPKISexp" type="base64Binary"/>
+    <any namespace="##other" processContents="lax" minOccurs="0"/>
+  </sequence>
+</complexType> 
+
+<!-- End SPKIData -->
+
+<!-- End KeyInfo -->
+
+<!-- Start Object (Manifest, SignatureProperty) -->
+
+<element name="Object" type="ds:ObjectType"/> 
+<complexType name="ObjectType" mixed="true">
+  <sequence minOccurs="0" maxOccurs="unbounded">
+    <any namespace="##any" processContents="lax"/>
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/> 
+  <attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
+  <attribute name="Encoding" type="anyURI" use="optional"/> 
+</complexType>
+
+<element name="Manifest" type="ds:ManifestType"/> 
+<complexType name="ManifestType">
+  <sequence>
+    <element ref="ds:Reference" maxOccurs="unbounded"/> 
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/> 
+</complexType>
+
+<element name="SignatureProperties" type="ds:SignaturePropertiesType"/> 
+<complexType name="SignaturePropertiesType">
+  <sequence>
+    <element ref="ds:SignatureProperty" maxOccurs="unbounded"/> 
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/> 
+</complexType>
+
+   <element name="SignatureProperty" type="ds:SignaturePropertyType"/> 
+   <complexType name="SignaturePropertyType" mixed="true">
+     <choice maxOccurs="unbounded">
+       <any namespace="##other" processContents="lax"/>
+       <!-- (1,1) elements from (1,unbounded) namespaces -->
+     </choice>
+     <attribute name="Target" type="anyURI" use="required"/> 
+     <attribute name="Id" type="ID" use="optional"/> 
+   </complexType>
+
+<!-- End Object (Manifest, SignatureProperty) -->
+
+<!-- Start Algorithm Parameters -->
+
+<simpleType name="HMACOutputLengthType">
+  <restriction base="integer"/>
+</simpleType>
+
+<!-- Start KeyValue Element-types -->
+
+<element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
+<complexType name="DSAKeyValueType">
+  <sequence>
+    <sequence minOccurs="0">
+      <element name="P" type="ds:CryptoBinary"/>
+      <element name="Q" type="ds:CryptoBinary"/>
+    </sequence>
+    <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
+    <element name="Y" type="ds:CryptoBinary"/>
+    <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
+    <sequence minOccurs="0">
+      <element name="Seed" type="ds:CryptoBinary"/>
+      <element name="PgenCounter" type="ds:CryptoBinary"/>
+    </sequence>
+  </sequence>
+</complexType>
+
+<element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
+<complexType name="RSAKeyValueType">
+  <sequence>
+    <element name="Modulus" type="ds:CryptoBinary"/> 
+    <element name="Exponent" type="ds:CryptoBinary"/> 
+  </sequence>
+</complexType> 
+
+<!-- End KeyValue Element-types -->
+
+<!-- End Signature -->
+
+</schema>
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index be542d5..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[tox]
-envlist = py27,py33,py34,py35,pypy
-
-[testenv]
-commands = 
-    pip install .[test]
-    py.test -vvv
-- 
python-zeep



More information about the tryton-debian-vcs mailing list