0

I am working on a project where I am seeking to provide an HTML form where users can enter values in form inputs, which would then be added to an XML file on submit.

So far, I have found examples of how to do this, but only at one level of XML data, for example a form with an input for "name" that submits to an XML file like the following:

    <meals><type>breakfast</type></meals>

Or perhaps like this:

    <meals>
       <meal>
          <type>breakfast</type>
       </meal>
    </meals>

I am seeking to use forms to write XML node content at an additional level, such as:

    <meals>
       <meal>
          <type>breakfast</type>
          <ingredients>
             <ing>eggs</ing>
          </ingredients>
       </meal>
       <meal>
          <type>dinner</type>
          <ingredients>
             <ing>pork chop</ing>
          </ingredients>
       </meal>
    </meals>

I have a form that provides for input of these elements, and a PHP script that writes them to an XML document, but I am not sure how to iterate over the nested arrays respective of their parent elements. When I submit the data above, the XML that I get is like the following:

    <meals>
       <meal>
          <type>breakfast</type>
          <ingredients>
             <ing>eggs</ing>
             <ing>pork chop</ing>
          </ingredients>
       </meal>
       <meal>
          <type>dinner</type>
          <ingredients>
             <ing>eggs</ing>
             <ing>pork chop</ing>
          </ingredients>
       </meal>
    </meals>

In other words, my PHP script creates an array of meals, and an array of ingredients, but I am wondering if there is a way to create nested arrays of meal>ingredients, or meal[i]ingredients.

Edit to add code for the HTML form and PHP script:

The HTML form:

    <form>
    <input name="done" value="done" type="submit">
    <fieldset name="meal">
       type: <input name="type[]" type="text">
       <br>
       Ingredients
       <fieldset name="ingredients">
          ing. name: <input name="ingName[]" type="text">
       </fieldset>
     </fieldset>
    <fieldset name="meal">
       type: <input name="type[]" type="text">
       <br>
       Ingredients
       <fieldset name="ingredients">
          ing. name: <input name="ingName[]" type="text">
       </fieldset>
     </fieldset>
    </form>

There is JS that allows for adding additional meal s and ingredient inputs.

Here is the PHP script:

    if(isset($_REQUEST['done']))
    {$xml = new DOMDocument("1.0","UTF-8");
     $xml->load("groceries4.xml");
     $rootTag=$xml->getElementsByTagName("groceries")->item(0);

     $mealTypes=$_REQUEST['type'];
        foreach($mealTypes as $mt)
        {$mealTag=$xml->createElement("meal");
         $mealType=$xml->createElement("type",$mt);
         $mealTag->appendChild($mealType);
         $ingrsTag=$xml->createElement("ingredients");
         $mealTag->appendChild($ingrsTag);
            $mealIngs=$_REQUEST['ingName'];
            foreach($mealIngs as $mi)
            {$ingTag=$xml->createElement("ing",$mi);
             $ingrsTag->appendChild($ingTag);};
         $rootTag->appendChild($mealTag);}; 


     $xml->save("groceries4.xml");
     }
    ?>
logan
  • 11
  • 1
  • Hi, you give an example of current expected and actual output, which is great, but we need to see the input and the current code (reduced down to a [mcve]) in order to understand where you're stuck. – IMSoP Feb 28 '18 at 19:32
  • Where is your PHP script, mentioned a bit but absent here? – Parfait Feb 28 '18 at 19:34
  • Hi, thanks for the responses. I was thinking my question was getting lengthy, so I cut it short before adding the PHP script (which I realize doesn't make too much sense). I changed a few semantic things from the actual code to make the question simpler and clearer, so I'm working on reconciling the code posted above with the PHP script I'm currently running. Hopefully I can edit the question soon. Thanks! – logan Feb 28 '18 at 19:52

1 Answers1

1

Many developers overlook how they name their input fields, particularly when it comes to related information.

In this particular case, it can make your life easier when you build the XML.

HTML

<form method="post">
    <!-- meal #1 -->
    <div class="meal">
        <h1>Meal #1</h1>
        <h2>Type</h2>
        <input type="text" name="meals[0][type]" value="m1 t" />
        <div class="ingredients">
            <h2>Ingredients</h2>
            <div class="ingredient">
                <h3>Ingredient #1</h3>
                <input type="text" name="meals[0][ingredients][0][inc]" value="m1 ing1" />
            </div>
            <div class="ingredient">
                <h3>Ingredient #2</h3>
                <input type="text" name="meals[0][ingredients][1][inc]" value="m1 ing2" />
            </div>
        </div>
    </div>
    <!-- meal #2 -->
    <div class="meal">
        <h1>Meal #2</h1>
        <h2>Type</h2>
        <input type="text" name="meals[1][type]" value="m2 t" />
        <div class="ingredients">
            <h2>Ingredients</h2>
            <div class="ingredient">
                <h3>Ingredient #1</h3>
                <input type="text" name="meals[1][ingredients][0][inc]" value="m2 ing1" />
            </div>
            <div class="ingredient">
                <h3>Ingredient #2</h3>
                <input type="text" name="meals[1][ingredients][1][inc]" value="m2 ing2" />
            </div>
        </div>
    </div>
    <!-- keep going -->
    <input type="submit" value="Save" />
</form>

Upon submission, it makes it easier to loop

PHP

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $doc = new DOMDocument('1.0', 'UTF-8');
    $xmlEl = $doc->createElement("xml");
    $xmlEl = $doc->appendChild($xmlEl);
    // add meals
    if (isset($_POST['meals'])) {
        $mealsEl = $doc->createElement("meals");
        $mealsEl = $xmlEl->appendChild($mealsEl);

        foreach ($_POST['meals'] as $meal) {
            // add meal
            $mealEl = $doc->createElement("meal");
            $mealEl = $mealsEl->appendChild($mealEl);
            // add meal type
            if (isset($meal['type'])) {
                $mealEl->appendChild($doc->createElement("type", $meal['type']));
            }
            // add meal ingredients
            if (isset($meal['ingredients'])) {
                $ingredientsEl = $doc->createElement("ingredients");
                $ingredientsEl = $mealEl->appendChild($ingredientsEl);

                foreach ($meal['ingredients'] as $ingredient) {
                    // add ingredient
                    $ingredientEl = $doc->createElement("ingredient");
                    $ingredientEl = $ingredientsEl->appendChild($ingredientEl);
                    // add inc
                    if (isset($ingredient['inc'])) {
                        $ingredientEl->appendChild($doc->createElement("inc", $ingredient['inc']));
                    }
                }
            }
        }
    }
    $doc->save("meals.xml");
}
?>

Though if you are clever enough, you can probably recursively build the XML as there is a pattern somewhere - unfortunately, I am not.

This answer is based off this answer.

Mikey
  • 6,728
  • 4
  • 22
  • 45