views:

1612

answers:

10

My question is best phrase as: http://stackoverflow.com/questions/262351/remove-a-child-with-a-specific-attribute-in-simplexml-for-php

except I'm not using simpleXML.

I'm new to XML for PHP so I may not be doing the best way

I have a xml created using the $dom->save($xml) for each individual user. (not placing all in one xml due to undisclosed reasons)

It gives me that xml declaration <?xml version="1.0"?> (no idea how to make it to others, but that's not the point, hopefully)

<?xml version="1.0"?>
<details>
 <person>name</person>
 <data1>some data</data1>
 <data2>some data</data2>
 <data3>some data</data3>
 <category id="0">
  <categoryName>Cat 1</categoryName>
  <categorydata1>some data</categorydata1>
 </category>
 <category id="1">
  <categoryName>Cat 2</categoryName>
  <categorydata1>some data</categorydata1>
  <categorydata2>some data</categorydata2>
  <categorydata3>some data</categorydata3>
  <categorydata4>some data</categorydata4>
 </category>
</details>

And I want to remove a category that has a specific attribute named id with the DOM class in php when i run a function activated from using a remove button.

the following is the debug of the function im trying to get to work. Can i know what I'm doing wrong?

function CatRemove($myXML){
     $xmlDoc = new DOMDocument();
     $xmlDoc->load( $myXML );
     $categoryArray = array();

     $main = $xmlDoc->getElementsByTagName( "details" )->item(0);

     $mainElement = $xmlDoc->getElementsByTagName( "details" );
     foreach($mainElement as $details){
      $currentCategory = $details->getElementsByTagName( "category" );
      foreach($currentCategory as $category){
       $categoryID = $category->getAttribute('id');
       array_push($categoryArray, $categoryID);
       if($categoryID == $_POST['categorytoremoveValue']) {
        return $categoryArray;
       }
      }
     }


     $xmlDoc->save( $myXML );
    }

Well the above prints me an array of [0]->0 all the time when i slot the return outside the if. is there a better way? I've tried using getElementbyId as well but I've no idea how to work that.

I would prefer not to use an attribute though if that would make things easier.

+1  A: 

So you want to remove the category node with a specific id?

$node = $xmlDoc->getElementById("12345");
if ($node) {
    $node->parentNode->removeChild($node);
}

You could also use XPath to get the node, for example:

$xpath = new DOMXpath($xmlDoc);
$nodeList = $xpath->query('//category[@id="12345"]');
if ($nodeList->length) {
    $node = $nodeList->item(0);
    $node->parentNode->removeChild($node);
}

I haven’t tested it but it should work.

Gumbo
You are faster that me. but that's the good answer.
stunti
parentNode->parentNode ? Aren't you going back once too far?
troelskn
(really gotta get used to this), i made an edit. and still am trying to understand the answer :P
not his fault, I made a mistake in my question
thx for editing it. I'll test it and let ya know.
tested. not working :(
@Alv: which method have you tested?
stunti
A: 

*invalid state.

A: 

*invalid state

If you want to use the getElementById() method, you first have to set the id attribute of each category node to be an ID using the setIdAttribute() method. And “$nodeList->length” checks if at least one node was found.
Gumbo
A: 

Tested both types. I'm afraid it's not working.

the first non-xpath method does not recognise the $node as a node that fits the parameter.

the other does not run the remove

It's for PHP5 right?
stunti
A: 

Can you try with this modified version:

function CatRemove($myXML, $id){
    $doc = new DOMDocument();
    $doc->loadXML($myXML);
    $xpath = new DOMXpath($doc);
    $nodeList = $xpath->query("//category[@id='$id']");
    foreach ($nodeList as $element) {
        $element->parentNode->removeChild($element);
    }

    echo htmlentities($doc->saveXML());
}

It's working for me. Just adapt it to your needs. It's not intended to use as-is, but just a proof of concept. You also have to remove the xml declaration from the string.

stunti
tried a few variations but still no go. some with no errors. and the present adopted solution tells me weird stuff.
A: 

here's my modified version that's not working still. No errors but not sure what's missing...

function CatRemove($myXML){
 $xmlDoc = new DOMDocument();
 $xmlDoc->load( $myXML );
 $IDtoRemove = $_POST['CatID'];

 //ADD REMOVE BIT HERE  
 $xmlDoc_string = $xmlDoc->saveXML(); 
 $xmlDoc->loadXML($xmlDoc_string); 
 $xpath = new DOMXpath($xmlDoc);
 $nodeList = $xpath->query("//category[@id='$IDtoRemove']");
 foreach ($nodeList as $element) {
  $element->parentNode->removeChild($element);
 }

 $xmlDoc->save( $myXML );
}

fails also if i switched

$nodeList = $xpath->query("//category[@id='$IDtoRemove']");

to

$nodeList = $xpath->query('//category[@id="'.$IDtoRemove.'"]');
Are you sure that “$_POST['categoryID']” has the correct value ({0,1}) to remove a category?
Gumbo
+1  A: 

Ok, let’s try this complete example of use:

function CatRemove($myXML, $id) {
    $xmlDoc = new DOMDocument();
    $xmlDoc->load($myXML);
    $xpath = new DOMXpath($xmlDoc);
    $nodeList = $xpath->query('//category[@id="'.(int)$id.'"]');
    if ($nodeList->length) {
     $node = $nodeList->item(0);
     $node->parentNode->removeChild($node);
    }
    $xmlDoc->save($myXML);
}

// test data
$xml = <<<XML
<?xml version="1.0"?>
<details>
 <person>name</person>
 <data1>some data</data1>
 <data2>some data</data2>
 <data3>some data</data3>
 <category id="0">
  <categoryName>Cat 1</categoryName>
  <categorydata1>some data</categorydata1>
 </category>
 <category id="1">
  <categoryName>Cat 2</categoryName>
  <categorydata1>some data</categorydata1>
  <categorydata2>some data</categorydata2>
  <categorydata3>some data</categorydata3>
  <categorydata4>some data</categorydata4>
 </category>
</details>
XML;
// write test data into file
file_put_contents('untitled.xml', $xml);
// remove category node with the id=1
CatRemove('untitled.xml', 1);
// dump file content
echo '<pre>', htmlspecialchars(file_get_contents('untitled.xml')), '</pre>';
Gumbo
we're getting somewhere. It did remove something. specifically ID="0". it can't remove any other nodes based on their id values.
Ok I foudn what caused the value to keep defaulting to 0 sicne i tried to use hardcoded values for a pre-test.Thanks for the support and answers.thanks Gumbo and stunti for the help.
A: 

Thanks for the support and answers.

thanks Gumbo and stunti for the help.

I'll love to send ya all bear hugs =D

I got it to work now :)

A: 

Thanks a lot to Gumbo.. I worked on that.. is it possible to edit the xml that means.. In that exmple, Cat 1 tag is there. shall i change it to Excellent? Can you please healp me?

A: 

the above funciton modified to remove an email from a mailing list

function CatRemove($myXML, $id) {
    $xmlDoc = new DOMDocument();
    $xmlDoc->load($myXML);
    $xpath = new DOMXpath($xmlDoc);
    $nodeList = $xpath->query('//subscriber[@email="'.$id.'"]');
    if ($nodeList->length) {
        $node = $nodeList->item(0);
        $node->parentNode->removeChild($node);
    }
    $xmlDoc->save($myXML);
}
$xml = 'list.xml';
$to = $_POST['email'];//user already submitted they email using a form 
CatRemove($xml,$to);
alex