Solved

removing xml elements and children

Posted on 2014-04-07
5
563 Views
Last Modified: 2014-04-10
I've been working on this project that gives my HR Department the ability to upload and edit job postings on our company's website by using xml to xsl to HTML (where the xml info can be edited) then back to xsl to xml (with new xml value changes in place). The uploader works, the HTML form generates the xml values correctly, and the edit feature works as well. The only problem I have is deleting elements from the xml. I tried to build a form with radio buttons that would make it easy for a "non-coder" to delete a job opportunity by just checking the radio button and clicking a submit button. So far the code I've tried to use does not delete any of the xml elements.

Here's an example of the xml I use:
<?xml version="1.0"?>
-<EMPLOYMENT_OPPORTUNITIES>
    -<OPPORTUNITY id="0">
          <INDEXABLE>0</INDEXABLE>
          <POSITION>CCR</POSITION>
          <DATELINE>05/15/2010</DATELINE>
          <LOCATION>files/CustomerCareRepresentative.pdf</LOCATION>
    </OPPORTUNITY>
   -<OPPORTUNITY id="1">
          <INDEXABLE>1</INDEXABLE>
          <POSITION>Staking Technician</POSITION>
          <DATELINE>05/15/2010</DATELINE>
          <LOCATION>files/StakingTechnician.pdf</LOCATION>
     </OPPORTUNITY>
</EMPLOYMENT_OPPORTUNITIES>

Open in new window


my php file looks like this:

(This is what creates the radio button display for each job the code loops through)
<html>
<head>
<title>Job Remover</title>
</head>
<body>
<form action="removejobs.php" method="post"  id="form1">

    <?php
     $Parent = 0;
     $Nodes = 0;
     $xmlLoad =simplexml_load_file("jobs.xml");
     foreach($xmlLoad ->children() as $x)
       {
        echo "Delete " . $x->getName() . ": " . $x->attributes() . "<br>"; 
        foreach($x ->children() as $child)
        {
			
        echo "<input type='radio' id='".$Parent."-". $child->getName() ."' name='" . $child->getName() . "' value='" . $child . "' />'". $child ."<br>";
			 
            $Nodes = $Nodes + 1;
        }
        echo "<br>";
        $Parent = $Parent + 1;
        }
     ?> 
     
        <button onclick='myFunction()' >Delete it</button>

</form>
</body>
</html>

Open in new window

The user would check each entry under each <opportunity> and then click the submit button to delete each OPPORTUNITY element (child nodes delete as well)


My removejobs.php code looks like this:

<?php

     $Nodes = 0;
     $Parent = 0;
     $xmlLoad =simplexml_load_file("jobs.xml");
	 
function myFunction()
	{
	 		
      foreach($xmlLoad ->children() as $x)
        {
            foreach($x ->children() as $child)
            { 
				  if(isset($_POST["INDEXABLE"]))
                {  
                    $child[0] = $_POST[$Parent . "-" . $child->removeChild()]; 
				}
				
                $Nodes = $Nodes + 1;
            }
            $Parent = $Parent + 1;
        }
		}
      $xmlLoad->asXML('jobs.xml');
      echo "File Updated"; 
	
?>

Open in new window



However, its not working correctly.

So my question is, how can I open the jobs.xml file, delete an <OPPORTUNITY> element and it's child nodes, and then resave jobs.xml (save as the same name)? The most important thing is that it has to be completely user friendly meaning the entire action has to be performed by the user using the jobRemover.php form

Thank you
files.zip
0
Comment
Question by:shart68
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 

Author Comment

by:shart68
ID: 39988823
Thanks, I appreciate the assistance.
0
 
LVL 43

Accepted Solution

by:
Rob earned 500 total points
ID: 39991258
Ok there was a bit I had to change:

<button> has to have type='submit'.  you had onclick="myFunction()" but the button expects that to be a javascript function, not a php one.  In otherwords you can't call php functions directly from javascript / html
Changed the <input> types to be checkboxes for more than one delete at a time
Changed the <input> name to essentially be an array of elements to delete.  Anything checked is put in this array
Changed the <input> values to be the parent index and the child name as this is the value that is passed in the array

index.php
<html>
<head>
<title>Job Remover</title>
</head>
<body>
<form action="removejobs.php" method="post"  id="form1">

    <?php
     $Parent = 0;
     $Nodes = 0;
     $xmlLoad = simplexml_load_file("jobs.xml");

     foreach($xmlLoad->children() as $x)
       {
        echo "Delete " . $x->getName() . ": " . $x->attributes() . "<br>";
        foreach($x->children() as $child)
        {

        echo "
        	<input
        		type='checkbox'
        		name='nodes[]'
        		value='".$Parent."-". $child->getName() ."'
        	/>'". $child ."<br>";

            $Nodes = $Nodes + 1;
        }
        echo "<br>";
        $Parent = $Parent + 1;
        }
     ?>
        <button type='submit'>Delete it</button>

</form>
</body>
</html>

Open in new window


In the removejobs there was quite a bit of change:
Removed the myFunction function as it is not relevant or available to call from the client
Code changed to loop through all submitted deletions and match them to a parent and child node
Use of unset to delete the node

removejobs.php
<?php

$xmlLoad = simplexml_load_file("jobs.xml");

$nodes = (isset($_POST["nodes"])) ? $_POST["nodes"] : array();

$opportunities = $xmlLoad->children();

foreach($nodes as $n) {
	list($p_index,$c_index)=explode("-",$n);
	$tmp=$opportunities[$p_index*1]->children();
	unset($tmp->$c_index);
}

echo "<br/>";

$xmlLoad->asXML('jobs.xml');

echo "File Updated";

?>

Open in new window


Please let me know if you need me to explain any of this further.

Rob
0
 

Author Closing Comment

by:shart68
ID: 39991404
Thank you for giving me a hand with this. For some reason, everytime I would try a search online for a solution, I would find either solutions that lead to dead ends, solutions using other languages (C#, Java, etc.) or partial resolutions. Before I go, would you mind giving me brief explanation of the three lines below (as this is my first time seeing this code).

list($p_index,$c_index)=explode("-",$n);
      $tmp=$opportunities[$p_index*1]->children();
      unset($tmp->$c_index);

Thanks again!
0
 
LVL 43

Expert Comment

by:Rob
ID: 39991482
My pleasure and that's what this site is here for; those solutions that you can't find anywhere else ;)

More than happy to explain those three lines (along with others if you want?)

list($p_index,$c_index)=explode("-",$n);
explode() just splits a string by a delimiter.  In your case we had the index of the parent separated from the child node name by using a dash, eg 0-INDEXABLE.

list() takes each element of an array and assigns it to each of the arguments you pass with the last one taking the remainding elements of the array if you pass less arguments than there are elements in the array.
eg list($var1, $var2, $var3) = array(1,2,3,4);
so that $var1 = 1, $var2 = 2, $var3 = [3,4];
In your case it meant i could assign the index of the parent to $p_index and the child node name to $c_index (maybe the variable should be called $c_name but don't worry about it!)

$tmp=$opportunities[$p_index*1]->children();
When parsed, the $p_index variable is treated as a string.  Multiplying it by 1 just converts it to an integer, which is required to index the array of OPPORTUNITY nodes.  The children of each OPPORTUNITY node are then assigned to a temporary variable $tmp

unset($tmp->$c_index);
There is no "deleteChild()" function so the way to do it is to delete the variable itself / unset it.  unset is a general php function (not specific to the simplexml class). Calling it on any variable will destroy that variable

HTH

Rob
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

These days socially coordinated efforts have turned into a critical requirement for enterprises.
Dramatic changes are revolutionizing how we build and use technology. Every company is automating, digitizing, and modernizing operations. We need a better, more connected way to work together as teams so we can harness the insights from our system…
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
The viewer will the learn the benefit of plain text editors and code an HTML5 based template for use in further tutorials.

626 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question