Gaz Smith
Gaz Smith

Reputation: 1108

PHP Remove XML node based on value

i'm trying to remove a specific node from XML using PHP. This is the structure of the XML :

<ArrivingFlights>
<flight>
    <to>Michelle</to>
    <from>Brianna xx</from>
    <imagepath>0001.jpg</imagepath>
    <templateStyle>template1</templateStyle>
    <time>17:00</time>
    <date>18/12/15</date>
</flight>
 <flight>
    <to>Ger</to>
    <from>Mammy xx</from>
    <imagepath>0002.jpg</imagepath>
    <templateStyle>template1</templateStyle>
    <time>08:00</time>
    <date>21/12/15</date>
</flight>
<flight>
    <to>Ciara</to>
    <from>Vikki xx</from>
    <imagepath>0003.jpg</imagepath>
    <templateStyle>template1</templateStyle>
    <time>11:00</time>
    <date>17/12/15</date>
</flight>
 </ArrivingFlights>

I have a PHP file that im using to get a FileName so i can remove a node based on that file name and replace it. This is my PHP :

<?php


    $id = $_GET['imagepath'];

$xmldoc = new DOMDocument();
$xmldoc->load('newcoke.xml');
$root   = $xmldoc->documentElement;
$fnode  = $root->firstChild;
// we retrieve the chapter and remove it from the book
$items = $xmldoc->getElementsByTagName('flight');
foreach ($items as $item){
    $node = $item->getElementsByTagName('imagepath')->item(0);
    if ($node->nodeValue == $id){
        $node->parentNode->removeChild($node);            
    }
}
$xmldoc->save('newXmlFile.xml');


?>

This SORT OF works, when i look at newFile.xml it is removing "ImagePath" but i wanted it to remove that whole "flight" node, so basically its parent. This is the result i get if i pass it 0001.jpg :

    <flight>
    <to>Michelle</to>
    <from>Brianna xx</from>

    <templateStyle>template1</templateStyle>
    <time>17:00</time>
    <date>18/12/15</date>
</flight>
 <flight>
    <to>Ger</to>
    <from>Mammy xx</from>
    <imagepath>0002.jpg</imagepath>
    <templateStyle>template1</templateStyle>
    <time>08:00</time>
    <date>21/12/15</date>
</flight>
<flight>
    <to>Ciara</to>
    <from>Vikki xx</from>
    <imagepath>0003.jpg</imagepath>
    <templateStyle>template1</templateStyle>
    <time>11:00</time>
    <date>17/12/15</date>
</flight>

Upvotes: 0

Views: 140

Answers (3)

Parfait
Parfait

Reputation: 107567

Consider using XSLT, the special-purpose language that restructures XML files. PHP maintains an XSLT 1.0 processor. Hence, there is no need for a foreach loop or if logic conditioning as the stylesheet script will handle such processing and very efficiently. You can even embed the script in PHP to dynamically pass the $id variable:

PHP with embedded XSLT

// Retrieve imagepath value
$id = $_GET['imagepath'];

// Load the XML source
$doc = new DOMDocument();
$doc->load('Flights.xml');

// Parse XSLT
$xsl = new DOMDocument;
$xslstr = '<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
           <xsl:output version="1.0" encoding="UTF-8" indent="yes" />
           <xsl:strip-space elements="*"/>

            <!-- Identity Transform -->
            <xsl:template match="@*|node()">
              <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
              </xsl:copy>
            </xsl:template>  

            <xsl:template match="flight[imagepath=\''.$id.'\']"/>
           </xsl:transform>';

$xsl->loadXML($xslstr);

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); 

// Transform XML source
$newXml = $proc->transformToXML($doc);

// Save output to file
$xmlfile ='Output.xml';
file_put_contents($xmlfile, $newXml);

Output

<?xml version="1.0" encoding="UTF-8"?>
<ArrivingFlights>
  <flight>
    <to>Ger</to>
    <from>Mammy xx</from>
    <imagepath>0002.jpg</imagepath>
    <templateStyle>template1</templateStyle>
    <time>08:00</time>
    <date>21/12/15</date>
  </flight>
  <flight>
    <to>Ciara</to>
    <from>Vikki xx</from>
    <imagepath>0003.jpg</imagepath>
    <templateStyle>template1</templateStyle>
    <time>11:00</time>
    <date>17/12/15</date>
  </flight>
</ArrivingFlights>

Upvotes: 1

TwoStraws
TwoStraws

Reputation: 13127

You can use parentNode as many times as you need to, although obviously it requires you to be confident your XML structure won't change. In this particular case you just need to go up one level further, like this:

$node->parentNode->parentNode->removeChild($node->parentNode);

But seeing as you're already in a loop where $item is being set, just remove that directly:

$item->parentNode->removeChild($item);

Upvotes: 0

u_mulder
u_mulder

Reputation: 54831

As flight is an $item, you should remove $item and not $node:

$item->parentNode->removeChild($item);

Upvotes: 0

Related Questions