writing hierarchical XML with HTML form/PHP - php

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");
}
?>

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.

Related

Why are the nested forms processed with $_SERVER['PHP_SELF'] (same html file) not displaying/processing correctly?

I'm trying to get user input in a progressive sequence that leads to that input being sent by email. Sending by email is a whole other issue that I haven't tackled yet so not really worried about that.
The part I am having difficulty with is once the user gets to the "Send Email?" (Yes/No) radio buttons, the input from that question is not processed correctly.
I've gotten further with this by using a separate php file as the form action but still get errors related to emailName, emailAddress, and emailMsg not existing ("Notice: Undefined index...").
Furthermore, I still need to be able to use the $_POST[athletes] array further down but I'm guessing it's outside of the variable scope at that point.
So to bring that all together, I'm really asking a few questions:
1) How can I get all of the forms to work together in the same file?
2) When the program actually goes past the "Send Email?" radio buttons when I use a separate php file as the form action, why am I getting undefined index errors?
3) Why do I get an error when I try to use the athletes[] array further down in the code? Should I somehow be passing the array values to that part of the code?
The exact steps the user would take to get to the issue is:
Select 1 or more athlete checkboxes and click the 'Display Selection(s)' button.
Select 'Yes' for "Send Email?" and click the 'Submit' button.
Restarts the code for some reason.
Any help would be greatly appreciated. Also, this is my first post so sorry if I asked the question incorrectly or not according to site etiquette.
I also apologize for the long code fragment but I'm not sure what parts might be causing this to be incorrect.
<b><h1><center>Athelete Selection Screen</center></h1></b>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
<p>
<fieldset>
<legend>Athletes Available: </legend>
<input type="checkbox" id="student1"
name="athletes[]" value="Student1 Test">
<label for="student1">Student1 Test</label><br/>
<font color="grey">Football - Running back</font><br/>
<p>
<input type="checkbox" id="student2"
name="athletes[]" value="Student2 Test">
<label for="student1">Student2 Test</label><br/>
<font color="grey">Soccer - Left Forward</font><br/>
</p>
<p>
<input type="checkbox" id="student3"
name="athletes[]" value="Student3 Test">
<label for="student1">Student3 Test</label><br/>
<font color="grey">Baseball - Pitcher/Left Outfield</font><br/>
</p>
</fieldset>
<p>
<?php echo("\t\t\t\t\t"); ?><button type="submit" name="submit" value="submit">Display Selection(s)</button>
</p>
</form>
<fieldset>
<legend>Athletes You Selected: </legend>
<?php
if (!empty($_POST['athletes']))
{
echo "<ul>";
foreach($_POST['athletes'] as $value)
{
echo "<li>$value</li>";
}
echo "</ul>";
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
<p>
<fieldset>
<legend>Send Email? </legend>
<input type="radio" id="Yes"
name="radioSendMsg[]" value="Yes">
<label for="student1">Yes</label>
<p>
<input type="radio" id="No"
name="radioSendMsg[]" value="No">
<label for="student1">No</label><br/>
</p>
<button type="submit" name="submitRadio" value="submit">Submit</button>
</p>
</form>
<?php
if (!empty($_POST['radioSendMsg']))
{
foreach($_POST['radioSendMsg'] as $radioMsg)
{
if($radioMsg == "Yes")
{
echo "\tPlease enter information regarding the email to be sent: ";
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
<p>
<label for="emailName"> Name: </label><br/>
<input type="text" size="25" id="emailName" name="emailName" />
</p>
<p>
<label for="emailAddress">E-mail Address: </label></br>
<input type="text" size="25" id="emailAddress" name="emailAddress" />
</p>
<p>
<textarea id="emailMsg" name="emailMsg" cols="30" rows="5"></textarea>
</p>
<button type="submit" name="emailSubmit" value="send">Send Message</button>
</form>
<?php
$msg = "Name: ".$_POST['emailName']."\n";
$msg.= "E-Mail: ".$_POST['emailAddress']."\n";
$msg.= "Message: ".$_POST['emailMsg']."\n";
$msg.= "<ul>";
foreach($_POST['athletes'] as $value)
{
$msg.= "<li>$value</li>\n";
}
$msg.= "</ul>";
$emailRecipient = "sjzerbib#gmail.com";
$emailSubject = "Athlete Selection Submission";
$emailHeaders = "From: Sebastien\n"."Reply-To: ".$_POST['emailAddress'];
mail($emailRecipient,$emailSubject,$msg,$emailHeaders);
echo "Message sent: \n".$msg;
}
else
{
?> <p /> <?php
echo "\n\nNo email will be sent for your last athlete selection.";
?>
<br/>Please click here
to return to the Athlete selection screen.
<?php
}
}
}
}
When you submit a form, only those controls contained within that form are included. The exception is successful controls that have the form attribute set to the id value of the form that was submitted.
So, given you had something like:
<form id="form-1" method="post">
<input type="text" name="first-input" />
</form>
<input type="text" name="second-input" />
The only value to be submitted would be that of first-input. If you add the form attribute to second-input:
<input type="text" name="second-input" form="form-1" />
Then the submission of the form would include both values. Unfortunately, the form attribute is not fully supported (IE and Edge have no support).
Of course, your markup is invalid, so that's a moot point. For starters, you cannot nest a form within a form. How a browser responds to markup that violates that rule is up to it's vendor, but in my experience is somewhat unpredictable. You're also using deprecated tags (<font> and <center> are no longer valid) and nesting elements incorrectly (<h1> is a block level element, whereas <b> is inline).
If you're doing a full submit each time (so the page gets submitted to itself and then reloads), then just use some sort of conditional to only render the dependent controls if the preceding form submissions were successful:
<?php
$canDoNextStep = !empty($_POST['input-1']);
?>
<form id="form-1" method="post">
<input type="text" name="first-input" />
<?php if(canDoNextStep): ?>
<input type="text" name="second-input" />
<?php endif; ?>
</form>
Lastly, whitespace is (mostly) ignored when your browser parses and displays your HTML, so you can lose the \t and \n values in your strings, unless you're concerned about how your markup looks if someone chooses to view source when using your form.

2 Forms calling the same Javascript function?

I've a page with two formulas one. Each one has it's own form with inputs etc. They both call the same Javascript function on key up.
Only the first one works, I kind of understand why but I can't find a resolution, I'm too new to Javascript to know how to tackle the problem. I can't change the structure of the JS file a great deal as other equations on other pages depend on this set up.
Is there a workaround?
Shortened HTML:
<div id="formula">
<p>To find ρ<sub>b</sub>:</p>
<form id="formula" name="formula">
<input type="hidden" id="formulaName" name="formulaName" value="porosityRhob"/>
<div>
<label>$\rho_{fl}$:</label>
<input type ="text" name="input" id="input" onkeyup="calculatePEFormula()"/>
</div>
<div>
<label>Result:</label>
<input type="text" id="result" name="result">
</div>
</form>
</div>
<br/>
<div id="formula">
<p>To find Φ:</p>
<form id="formula" name="formula">
<input type="hidden" id="formulaName" name="formulaName" value="porosityPhi"/>
<div>
<label>$\rho_{ma}$:</label>
<input type ="text" name="input" id="input" onkeyup="calculatePEFormula()"/>
</div>
<div>
<label>Result:</label>
<input type="text" id="result" name="result">
</div>
</form>
</div>
THE JS:
function PEFormula(result, formulaName){
this.result = result;
this.formulaName = formulaName;
}
function calculatePEFormula(){
var PEObject = new PEFormula($("#result"), $("#formulaName"));
var formulaName = $("#formulaName").val();
switch(formulaName){
case "porosityRhob" : PEObject.porosityRhoB();
break;
case "porosityPhi" : PEObject.porosityPhi();
break;
}
PEFormula.prototype.porosityPhi = function(){
var input = parseFloat($("#input").val());
//logic
return r;
}
The HTML attribute id is supposed to be unique
<div id="formula">
<form id="formula" name="formula">
<input type="hidden" id="formulaName" name="formulaName" value="porosityRhob"/>
<input type ="text" name="input" id="input" onkeyup="calculatePEFormula()"/>
<input type="text" id="result" name="result">
Try changing these ids instead use classes
Here is the solution change all field ids to class and form id should be different and pass parameter id of form as parameter onkeyup="calculatePEFormula('form#formula1')" and onkeyup="calculatePEFormula('form#formula2')" Now in js
function PEFormula(result, formulaName){
this.result = result;
this.formulaName = formulaName;
}
function calculatePEFormula(form_id){
var PEObject = new PEFormula($(form_id+" .result"), $(form_id+" .formulaName"));
var formulaName = $(form_id+" .formulaName").val();
switch(formulaName){
case "porosityRhob" : PEObject.porosityRhoB();
break;
case "porosityPhi" : PEObject.porosityPhi();
break;
}
PEFormula.prototype.porosityPhi = function(){
var input = parseFloat($(form_id+" .input").val()); //provide the form id here
//logic
return r;
}
You're using ID's when you should be using classes.
You need to avoid assigning the same id attribute to multiple elements. An element's ID should be unique.
Never use the same id for multiple elements. That's a basic concept in HTML. An identification should be unique and identical. So there cannot be any duplicated IDs inside any HTML page. So please change the ids of 2nd form,
<div id="formula2">
<p>To find Φ:</p>
<form id="formula2" name="formula">
<input type="hidden" id="formulaName2" name="formulaName" value="porosityPhi"/>
<div>
<label>$\rho_{ma}$:</label>
<input type ="text" name="input" id="input2" onkeyup="calculatePEFormula()"/>
</div>
<div>
<label>Result:</label>
<input type="text" id="result2" name="result">
</div>
</form>
</div>
Change the IDs accordingly when calling the same js function.
I have renamed all the IDs by adding 2 at the end of each ID. Make every ID unique.

How to send a result to a form with php?

I'm really new to PHP but it's awesome language :)
I created simple mathematical calculation script that takes inputs from forms in terms of variables and perform simple calculations. I would like a result to be displayed in another form instead of simply being displayed at the bottom of the page.
<html>
<body>
<p>Simple PHP script for cloning calculations</p>
<form name="form1" method="post" action="">
<p>
<label for="vector_lenght">La taille du vecteur (kb)</label>
<input type="text" name="vector_lenght" id="vector_lenght">
</p>
<p>
<label for="insert_lenght">La taille de l'insert (kb)</label>
<input type="text" name="insert_lenght" id="insert_lenght">
</p>
<p>
<label for="conc_insert">La concentration de l'insert</label>
<input type="text" name="conc_insert" id="conc_insert">
</p>
<p>
<input type="submit" name="ratio_calc" id="ratio_calc" value="Calculer">
</p>
<p>
<label for="ratio">Le ratio à utiliser</label>
<input type="text" name="ratio" id="ratio">
</p>
<p>
<label for="ratio_1">ratio 1:1</label>
<input type="text" name="ratio_1" id="ratio_1">
<br>
<label for="ratio_3">ratio 1:3</label>
<input type="text" name="ratio_3" id="ratio_3">
<br>
<label for="ratio_5">ratio 1:5</label>
<input type="text" name="ratio_5" id="ratio_5">
</p>
</form>
<?php
if($_POST['ratio_calc']!=''){
define("conc_vector", 100);
$vector_lenght = $_POST['vector_lenght'];
$insert_lenght = $_POST['insert_lenght'];
$conc_insert = $_POST['conc_insert'];
$result = (conc_vector * $insert_lenght) / $vector_lenght;
echo "<h1>$result</h1>";
}
?>
</body>
</html>
In your opening form tag, the 'action' attribute specifies what file should receive the HTTP request created when you submit the form. As it is now the value is an empty string, and the script is defaulting to POSTing the data back to the current script.
(I assume this other form is in a different page - if not, skip to the last code snippet)
So, create another PHP script that represents the page you want to contain your results, and put the name of the new script as the value of the 'action' attribute. In the new script, you can retrieve the values sent by your form via the $_POST[] superglobal (in the same way that you already are in the code you posted).
If the new page is named resultPage.php (and is in the same directory as the script you posted), your form tag should look like this:
<form name="form1" method="post" action="resultPage.php">
If you want the data to display inside a form in the new page, do something like this:
<input type="text" value="<?php echo $_POST['conc_insert'] ?>">

Form is returned with HTML tags (for use as a template)

I would like to make a form where users can enter text, and when the form is submitted it will return an output in HTML. The form is for use by me and my colleagues, not end users. We are looking for this solution in order to better style our website's content. We use Wordpress but have failed to find a solution to this issue. (We currently use a basic HTML template, but that makes for time-consuming work when you look at the example below).
Here's how I envisage this form:
<form>
Artist name: <input type="text" name="artist"><br />
Track name: <input type="text" name="track"><br />
Artist link: <input type="text" name="artistlink"><br />
Lyrics name: <input type="text" name="lyrics">br />
</form>
I can do the above part fine. Then the more complicated is making the output contain HTML tags. I want something like this:
<strong>Artist:</strong> <div id="artistname">artist's name</div>
<strong>Track:</strong> <div id="trackname>track name</div>
<strong>Lyrics:</strong> <div id="lyricstext" style="overflow: auto; height: 360px; width: 640px;">
<ul>
<ul>
<li>Its the two kids</li>
<li>New shit improving the movement</li>
<li>We prove this with music</li>
<li>Words for the chosing</li>
</ul>
</ul>
</div>
This way, I can add a jQuery snippet like so:
<script type="text/javascript">
$(function() {
$("ul li:nth-child("odd")").addClass("even");
});
</script>
To be able to style the odd and even <li> differently. I also have greater control over each aspect of the output by creating divs for each part.
I essentially need this as a template for putting our content on the site.
Hope my question is understandable!
Thanks.
Are you looking for something like this?
<form method="POST" action="">
Artist name: <input type="text" name="artist"><br />
Track name: <input type="text" name="track"><br />
Artist link: <input type="text" name="artistlink"><br />
Lyrics name: <input type="text" name="lyrics"><br />
<input type="submit" value="OK" />
</form>
<?php
//check if the submit button has been pressed and if the artist value is not empty
if(isset($_POST['artist']) && $_POST['artist'] != "") {
echo '<strong>Artist:</strong><div id="artistname>"'.$_POST['artist'].'</div>';
}
?>

Form / ajax / PHP issue

I am trying to make a small form that lets the user pick one element from 3 different radiobutton lists to set one element as the users active element (that will be stored to MySQL). Somehow along the way it does not work and I can not seem to figure out why, perhaps someone of you can see what I did wrong?
HTML:
<form name="activeForm1" method="post">
<fieldset data-role="controlgroup">
<div class="ui-radio">
<input type="radio" name="active" value="1" id="1">
<label for="1"></label></input>
</div>
<div class="ui-radio">
<input type="radio" name="active" value="2" id="2">
<label for="2"></label></input>
</div>
<div class="ui-radio">
<input type="radio" name="active" value="3" id="3">
<label for="3"></label></input>
</div>
</fieldset>
<div data-role="footer">
<input type="submit" href="#" onclick="setActive(1)"/>
</div>
</form>
JavaScript / Ajax call
function setActive(formid)
{
$.ajax(
{
type:'POST',
url:'active.php',
data:$('#activeForm'+formid).serialize(),
success:function(response)
{
}
}
);
}
PHP code:
session_start();
include('connectToDb.php');
$id = $_SESSION['id'];
if (isset($_POST['active']))
{
$formValue = $_POST['active'];
mail('my#mail.com','Test',$formValue,'From: dummy#mail.com');
mysql_query(/* UPDATE MySQL */);
header("Location: main.php");
}
else
{
mail('my#mail.com','Test','No data recieved!','From: dummy#mail.com');
}
So it works up until the if (isset($_POST['active'])) but then mails me that no data was recieved. I already have 2 similar forms on the same page and they are way bigger and has no problems running. Can't figure out what I did wrong here.
Wrong code :
data:$('#activeForm'+formid).serialize(),
#activeForm is not an id, it is the name of the form tag,
Correct the form tag to,
<form name="activeForm1" id="activeForm1" method="post">
Replace following line
data:$('#activeForm'+formid).serialize(),
with
data: $('form[name="activeForm'+formid+'"]').serialize(),
change
<input type="submit" href="#" onclick="setActive(1)"/>
to
<input type="button" href="#" onclick="setActive(1)"/>
and then it should work

Categories