Entry Form - Multiple Entries & Entry Type & Parent
A little bit late but here it is.


Go to https://pluginfactory.io/ and create a plugin, you need at least 1 Controller but you can leave the Name value blank to create a controller with the same Name as your PluginHandle. So if you choose "Experiment" as your Pluginhandle your controller will be ExperimentController
Click on "Build my Plugin" and save the files in your craft/plugins/&gt;&gt;pluginhandle&lt;&lt; folder (of course you need to create the >>pluginhandle&lt;&lt; directory eg.) Then you should install the plugin
Insert this function in your controller. Note: this is just an example. I don't know your fieldLayout or some special behaviors you might want to include. So this is just the basic logic with some error handling. Important please read the commands and change the entryType Ids

     /**
     * @var    bool|array Allows anonymous access to this controller's actions.
     * @access protected
     */
    protected $allowAnonymous = true;

    /**
     * @throws Exception
     */
    public function actionSaveEntry(){
        $this-&gt;requirePostRequest();
        // check for an Id if there is one we update an existing entry if not we create a new one
        if($entryId = craft()-&gt;request-&gt;getParam('entryId')){
            if(!$entry = craft()-&gt;elements-&gt;getElementById($entryId)){
                throw new Exception('Could not find entry with id');
            }
        }else{
            $entry = new EntryModel();
            $entry-&gt;typeId = craft()-&gt;request-&gt;getParam('entryType');
            $entry-&gt;sectionId = craft()-&gt;request-&gt;getParam('sectionId');
        }

        // set the content of your entry/experiment
        $entryData = craft()-&gt;request-&gt;getParam('experiment');
        $entry-&gt;getContent()-&gt;setAttributes($entryData['fields']);

        // try to save the entry
        if(craft()-&gt;entries-&gt;saveEntry($entry)){
            // fetch the id from the experiment so we can use that as a parentId for the cage
            $entryId = $entry-&gt;id;
            // if everything is alright we can save the cage like we did it with the experiment
            if($cagesData = craft()-&gt;request-&gt;getParam('cage')){

                foreach ($cagesData as $cageData){
                    // like with the entry check for an Id
                    if($cageId = $cageData['entryId']){
                        if(!$cage = craft()-&gt;elements-&gt;getElementById($cageId)){
                            throw new Exception('Could not find cage with the given Id');
                        }
                    }else{
                        $cage = new EntryModel();
                        $cage-&gt;typeId = 5; // you could as well create a hidden field like for the entry itself but you must change the typeId to your entryType Id
                        $cage-&gt;sectionId = craft()-&gt;request-&gt;getParam('sectionId');
                    }

                    // save the content as well
                    $cage-&gt;getContent()-&gt;setAttributes($cageData['fields']);
                    // and set the parent
                    $cage-&gt;parentId = $entryId;
                    if(craft()-&gt;entries-&gt;saveEntry($cage)){
                        $cageId = $cage-&gt;id;
                        // and now we are going to do the same with the animals
                        if($rodentsData = $cageData['rodents']) {
                            $rodentErrors = [];
                            foreach ($rodentsData as $rodentData){
                                // like with the entry check for an Id
                                if (array_key_exists('entryId', $rodentData) &amp;&amp; $rodentId = $rodentData['entryId']) {
                                    if (!$rodent = craft()-&gt;elements-&gt;getElementById($rodentId)) {
                                        throw new Exception('Could not find rodent with the given Id');
                                    }
                                } else {
                                    $rodent = new EntryModel();
                                    $rodent-&gt;typeId = 6; // change your entryType Id here
                                    $rodent-&gt;sectionId = craft()-&gt;request-&gt;getParam('sectionId');
                                }

                                $rodent-&gt;getContent()-&gt;setAttributes($rodentData['fields']);
                                $rodent-&gt;parentId = $cageId;
                                if (!craft()-&gt;entries-&gt;saveEntry($rodent)) {
                                    // important note: if there are any errors here, the cage and the experiment is
                                    // saved anyway so you should insert the id of the experiment to the form in order
                                    // to update the form instead of creating a new one again and again
                                    // if the experiment has an Id but the cage/rodent not you'll just update the experiment
                                    // and create new cages/rodents for it
                                    $rodentErrors[] = $rodent-&gt;getErrors();
                                }else{
                                    $rodentErrors = [];
                                }
                            }
                            // include errors of each item
                            craft()-&gt;urlManager-&gt;setRouteVariables(array(
                                'rodentErrors' =&gt; $rodentErrors
                            ));
                        }
                    }else{
                        craft()-&gt;urlManager-&gt;setRouteVariables(array(
                            'cageErrors' =&gt; $cage-&gt;getErrors()
                        ));
                    }
                }

            }
        }else{
            // handle your errors here.. you can use $entry-&gt;getErrors()
            // return them to your frontend and render them in twig or something
            craft()-&gt;urlManager-&gt;setRouteVariables(array(
                'experimentErrors' =&gt; $entry-&gt;getErrors()
            ));
        }
    }

Your html template. Note I don't know your fieldLayout so I just included the title and the craft default body field. In order to add your custom fields to the html you need to set the input name to entryType[fields][fieldHandle] so if you want to add a field with the handle foo to the cage you would name it cage[fields][foo]. As for the routing: your action must be pluginHandle/functionName

&lt;form method="post" accept-charset="UTF-8"&gt;
    {{ getCsrfInput() }}
    {# your plugin name and function name #}
    &lt;input type="hidden" name="action" value="test/saveEntry"&gt;
    {# the id of your section for me its 4 you need to change this value to your section Id #}
    &lt;input type="hidden" name="sectionId" value="4"&gt;
    {# enable the entry #}
    &lt;input type="hidden" name="enabled" value="1"&gt;
    {# id of your entry leave it blank to insert a new entry, insert a id to change an existing entry#}
    &lt;input type="hidden" name="entryId" value=""&gt;
    {# the id of your experiments entryType for me its 4 you need to change this value #}
    &lt;input type="hidden" name="entryType" value="4"&gt;

    &lt;label for="title"&gt;Title&lt;/label&gt;
    &lt;input id="title" type="text" name="experiment[fields][title]"&gt;
    &lt;input  type="text" name="experiment[fields][body]"&gt;

    {# now the cage as a children #}
    &lt;div&gt;
        &lt;label for="title"&gt;cage title&lt;/label&gt;
        &lt;input type="text" name="cage[0][fields][title]"&gt;
        &lt;input type="text" name="cage[0][fields][body]"&gt;
        &lt;input type="hidden" name="cage[0][entryId]" value=""&gt;
        {# and some Rodents as children for the cages #}
        &lt;div&gt;
            &lt;label for="title"&gt;Rodent title&lt;/label&gt;
            &lt;input type="text" name="cage[0][rodents][0][fields][title]"&gt;
            &lt;input type="text" name="cage[0][rodents][0][fields][body]"&gt;
            &lt;input type="hidden" name="cage[0][rodents][0][entryId]" value=""&gt;
        &lt;/div&gt;

        &lt;div&gt;
            &lt;label for="title"&gt;Rodent title&lt;/label&gt;
            &lt;input type="text" name="cage[0][rodents][1][fields][title]"&gt;
            &lt;input type="text" name="cage[0][rodents][1][fields][body]"&gt;
            &lt;input type="hidden" name="cage[0][rodents][1][entryId]" value=""&gt;
        &lt;/div&gt;

        &lt;div&gt;
            &lt;label for="title"&gt;Rodent title&lt;/label&gt;
            &lt;input type="text" name="cage[0][rodents][2][fields][title]"&gt;
            &lt;input type="text" name="cage[0][rodents][2][fields][body]"&gt;
            &lt;input type="hidden" name="cage[0][rodents][2][entryId]" value=""&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    {# and another cage #}
    &lt;div&gt;
        &lt;label for="title"&gt;cage title&lt;/label&gt;
        &lt;input type="text" name="cage[1][fields][title]"&gt;
        &lt;input type="text" name="cage[1][fields][body]"&gt;
        &lt;input type="hidden" name="cage[1][entryId]" value=""&gt;
        {# and some Rodents as children for the cages #}
        &lt;div&gt;
            &lt;label for="title"&gt;Rodent title&lt;/label&gt;
            &lt;input type="text" name="cage[1][rodents][0][fields][title]"&gt;
            &lt;input type="text" name="cage[1][rodents][0][fields][body]"&gt;
            &lt;input type="hidden" name="cage[1][rodents][0][entryId]" value=""&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;input type="submit" value="Publish"&gt;




{# just as an example how you could display errors or at least receive the error object #}
{% if rodentErrors is defined %}
    {% for errors in rodentErrors %}
        {% for fieldHandle, errorMessages in errors  %}
            {{ fieldHandle }} {{ errorMessages[0] }}&lt;br&gt;
        {% endfor %}
    {% endfor %}
{% endif %}



Please let me know when you need help and feel free to ask what you like.
If done right, you'll end up with a structure like this with your form (note: please ignore the titles...)