XML edit in php - php

In an xml file I have this structure (with <post>repeating) :
<data>
<post>
<deal_id>479</deal_id>
<deal_title><![CDATA[Δίπλωμα Μηχανής, στη Σχολή Οδηγών Παραστατίδης στον Εύοσμο, μόνο με 49€]]></deal_title>
<deal_url>http://domain.com/site/shop/autokinito-el/diplwma-mixanis-sxoli-odigwn-parastatidis-euosmos/</deal_url>
<deal_city><![CDATA[Θεσσαλονίκη]]></deal_city>
<deal_price><![CDATA[49]]></deal_price>
<deal_previous_price><![CDATA[125]]></deal_previous_price>
<deal_discount><![CDATA[60.8]]></deal_discount>
<deal_start><![CDATA[2016-01-10 00:00:00]]></deal_start>
<deal_end><![CDATA[2016-04-01 00:00:00]]></deal_end>
<deal_image>
<image>
<file>http://domain.com/site/wp-content/uploads/2015/09/c700x420.jpg</file>
<title>c700x420</title>
<caption></caption>
<description></description>
<alt></alt>
</image>
<image>
<file>http://domain.com/site/wp-content/uploads/2015/09/diploma1.jpg</file>
<title>diploma1</title>
<caption></caption>
<description></description>
<alt></alt>
</image>
</deal_image>
<deal_sales><![CDATA[0]]></deal_sales>
<deal_active><![CDATA[true]]></deal_active></post></data>
and I would like to transform the <deal_image> to
<deal_image>http://domain.com/site/wp-content/uploads/2015/09/c700x420.jpg</deal_image>
which means keep only the first appearing jpg and discard the rest..and do that for all <post>
How can I do that with php?
So the desired output would be something like this:
<data>
<post>
<deal_id>479</deal_id>
<deal_title><![CDATA[Δίπλωμα Μηχανής, στη Σχολή Οδηγών Παραστατίδης στον Εύοσμο, μόνο με 49€]]></deal_title>
<deal_url>http://domain.com/site/shop/autokinito-el/diplwma-mixanis-sxoli-odigwn-parastatidis-euosmos/</deal_url>
<deal_city><![CDATA[Θεσσαλονίκη]]></deal_city>
<deal_price><![CDATA[49]]></deal_price>
<deal_previous_price><![CDATA[125]]></deal_previous_price>
<deal_discount><![CDATA[60.8]]></deal_discount>
<deal_start><![CDATA[2016-01-10 00:00:00]]></deal_start>
<deal_end><![CDATA[2016-04-01 00:00:00]]></deal_end>
<deal_image>http://domain.com/site/wp-content/uploads/2015/09/c700x420.jpg</deal_image>
<deal_sales><![CDATA[0]]></deal_sales>
<deal_active><![CDATA[true]]></deal_active></post></data>
Note that the deal_image tag kept only the url of the first image and ignored the rest. In my xml file there are lots of <post></post> sections, which should also be processed in an iteration.

First we remove all image childs of deal_image, then we assign the image value to deal_image
<?php
$dom = new DOMDocument();
$dom->formatOutput = true;
$dom->loadXML('<data>
<post>
<deal_id>479</deal_id>
<deal_title><![CDATA[Δίπλωμα Μηχανής, στη Σχολή Οδηγών Παραστατίδης στον Εύοσμο, μόνο με 49€]]></deal_title>
<deal_url>http://domain.com/site/shop/autokinito-el/diplwma-mixanis-sxoli-odigwn-parastatidis-euosmos/</deal_url>
<deal_city><![CDATA[Θεσσαλονίκη]]></deal_city>
<deal_price><![CDATA[49]]></deal_price>
<deal_previous_price><![CDATA[125]]></deal_previous_price>
<deal_discount><![CDATA[60.8]]></deal_discount>
<deal_start><![CDATA[2016-01-10 00:00:00]]></deal_start>
<deal_end><![CDATA[2016-04-01 00:00:00]]></deal_end>
<deal_image>
<image>
<file>http://domain.com/site/wp-content/uploads/2015/09/c700x420.jpg</file>
<title>c700x420</title>
<caption></caption>
<description></description>
<alt></alt>
</image>
<image>
<file>http://domain.com/site/wp-content/uploads/2015/09/diploma1.jpg</file>
<title>diploma1</title>
<caption></caption>
<description></description>
<alt></alt>
</image>
</deal_image>
<deal_sales><![CDATA[0]]></deal_sales>
<deal_active><![CDATA[true]]></deal_active></post></data>');
$featuredde1 = $dom->getElementsByTagName('image');
foreach ($featuredde1 as $node) {
$node->parentNode->removeChild($node);
}
foreach ($featuredde1 as $node) {
$node->parentNode->removeChild($node);
}
$data = $dom->getElementsByTagName( "deal_image" );
$data ->item(0)->nodeValue = "http://domain.com/site/wp-content/uploads/2015/09/c700x420.jpg";
echo $dom->saveXML();
DEMO
http://ideone.com/HlrKM4

You can use DOMDocument with DOMXPath:
$dom = new DOMDocument();
$dom->loadXML( $xml, LIBXML_NOBLANKS );
$xpath = new DOMXPath( $dom );
foreach( $xpath->query( '/data/post/deal_image' ) as $deal_image )
{
$value = $xpath->query( './image/file', $deal_image )->item(0)->nodeValue;
$new_node = $dom->createElement( 'deal_image', $value );
$deal_image->parentNode->replaceChild( $new_node, $deal_image );
}
$dom->formatOutput = True;
echo $dom->saveXML().PHP_EOL;
($xml is your XML string; if you want load XML directly from a file, you can use $dom->load( $filePath ) instead of $dom->loadXML( $xml ) )
After init of DOMDocument and DOMXPath, the foreach loop examine all <deal_image> nodes, find the value of first <image><file>, create a new <deal_image> with this found value and replace old <deal_image> with the new created.
In the demo above I have added two more <post> to test the behavior with 1 or 3 images.
See more about DOMDocument
See more about DOMXPath

Related

Xml Append/Add new node php

I'm trying to update and add node to a xml file. Currently I can create and overwrite the file with my new node, however what I need to do is do to is add the new node to the existing file (.xml) and I am exhausted. I am new to php (I've tried all every code on this site and this is my current code can't be added here ... please Help
$doc = new DOMDocument;
// Load the XML
///$doc->loadXML("<root/>");
//---- ///$xml = new Document;
///$xml ->loadXML($xml);
//$xml = simplexml_load_file("pole.xml");
$title = $_POST["title"];
$xml = <<<XML <item> <title>$title</title> </item> XML;
$xml = new Document;
$xml ->loadXML($xml);
$xml ->appendXML($xml);
$xml = new SimpleXMLElement($xml);
echo $xml->saveXML('pole.xml');
I can offer no advice for using SimpleXML but as the above does attempt at using DOMDocument perhaps the following simple example will be of use.
$filename='pole.xml';
# Stage 1
# -------
// Create an instance of DOMDocument and then
// generate whatever XML you need using DOMDocument
// and save.
libxml_use_internal_errors( true );
$dom=new DOMDocument('1.0','utf-8');
$dom->formatOutput=true;
$dom->preserveWhiteSpace=true;
$root=$dom->createElement('Root');
$dom->appendChild( $root );
$item=$dom->createElement('Item');
$title=$dom->createElement('title','Hello World');
$item->appendChild( $title );
$root->appendChild( $item );
$dom->save( $filename );
$dom=null;
This yields the following XML:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Item>
<title>Hello World</title>
</Item>
</Root>
To then modify the XML file you have created or downloaded etc:
# Stage 2
# -------
// A new instance of DOMDocument is NOT strictly necessary here
// if you are continuing to work with the generated XML but for the purposes
// of this example assume stage 1 and stage 2 are done in isolation.
// Find the ROOT node of the document and then add some more data...
// This simply adds two new simple nodes that have various attributes
// but could be considerably more complex in structure.
$dom=new DOMDocument;
$dom->formatOutput=true;
$dom->preserveWhiteSpace=false;
$dom->load( $filename );
# Find the Root node... !!important!!
$root=$dom->getElementsByTagName('Root')->item(0);
# add a new node
$item=$dom->createElement('Banana','Adored by monkeys');
$attributes=array(
'Origin' => 'Central America',
'Type' => 'Berry',
'Genus' => 'Musa'
);
foreach( $attributes as $attr => $value ){
$attr=$dom->createAttribute( $attr );
$attr->value=$value;
$item->appendChild( $attr );
}
#ensure that you add the new node to the dom
$root->appendChild( $item );
#new node
$item=$dom->createElement('Monkey','Enemies of Bananas');
$attributes=array(
'Phylum' => 'Chordata',
'Class' => 'Mammalia',
'Order' => 'Primates'
);
foreach( $attributes as $attr => $value ){
$attr=$dom->createAttribute( $attr );
$attr->value=$value;
$item->appendChild( $attr );
}
$root->appendChild( $item );
$dom->save( $filename );
$dom=null;
This modifies the XML file and yields the following:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Item>
<title>Hello World</title>
</Item>
<Banana Origin="Central America" Type="Berry" Genus="Musa">Adored by monkeys</Banana>
<Monkey Phylum="Chordata" Class="Mammalia" Order="Primates">Enemies of Bananas</Monkey>
</Root>

PHP - Finding and removing an XML node via DOM

Can anyone please point out why the PHP below isn't deleting the XML node?
I'm wanting to delete the entire image node that contains the original_number value of 823.
Thanks in advance.
$xml = '<?xml version="1.0"?>
<property>
<edited>true</edited>
<images>
<image>
<is_required><![CDATA[true]]></is_required>
<original_number><![CDATA[823]]></original_number>
</image>
<image>
<is_required><![CDATA[true]]></is_required>
<original_number><![CDATA[555]]></original_number>
</image>
</images>
</property>';
$originalNumberToDelete = 823;
$dom = new DOMDocument();
$dom->loadXML( $xml->asXML(), LIBXML_NOBLANKS );
$dom->formatOutput = true;
$xpath = new DOMXPath($dom);
foreach( $xpath->query("property/images/image[original_number='".$originalNumberToDelete."']") as $node) {
$node->parentNode->removeChild($node);
}
echo $dom->saveXML();
Maybe a possible solution is to change
$dom->loadXML( $xml->asXML(), LIBXML_NOBLANKS );
to
$dom->loadXML( $xml, LIBXML_NOBLANKS );
Then start your xpath expression with a double forward slash:
$xml = '<?xml version="1.0"?>
<property>
<edited>true</edited>
<images>
<image>
<is_required><![CDATA[true]]></is_required>
<original_number><![CDATA[823]]></original_number>
</image>
<image>
<is_required><![CDATA[true]]></is_required>
<original_number><![CDATA[555]]></original_number>
</image>
</images>
</property>';
$originalNumberToDelete = 823;
$dom = new DOMDocument();
$dom->loadXML( $xml, LIBXML_NOBLANKS );
$dom->formatOutput = true;
$xpath = new DOMXPath($dom);
foreach( $xpath->query("//property/images/image[original_number='".$originalNumberToDelete."']") as $node) {
$node->parentNode->removeChild($node);
}
echo $dom->saveXML();
Demo

XML PHP Delete specific Child if?

I have a xml document looking like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<library>
<invites>
<invite>
<username>0</username>
<userid>0</userid>
</invite>
<invite>
<username>Danielle</username>
<gameid>87808</gameid>
</invite>
<invite>
<username>Petra</username>
<userid>978</userid>
</invite>
</invites>
</library>
Now, I want to delete the <invite> with Danielle but I am not sure how? I am using this right now but this will only delete the first record?
$file = 'my.xml';
$fp = fopen($file, "rb") or die("cannot open file");
$str = fread($fp, filesize($file));
$xml = new DOMDocument("1.0", "ISO-8859-1");
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$xml->loadXML($str) or die("Error");
$root = $xml->documentElement;
$fnode = $root->firstChild;
$ori = $fnode->childNodes->item(0);
$fnode->removeChild($ori);
$xml->save($file);
I want to be able to delete depending on either gameid or userid. How do I go about this?
Thanks in advance :-)
You could use XPath to select all nodes that have a certain userid or gameid: http://www.w3schools.com/xpath/default.asp
Try this:
Using DOM & DOMXPath.
<?php
$dom = new DOMDocument( '1.0' );
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
// load the xml file
$dom->loadXML( '<?xml version="1.0" encoding="ISO-8859-1"?>
<library>
<invites>
<invite>
<username>0</username>
<userid>0</userid>
</invite>
<invite>
<username>Danielle</username>
<gameid>87808</gameid>
</invite>
<invite>
<username>Petra</username>
<userid>978</userid>
</invite>
</invites>
</library>', LIBXML_NOBLANKS );
$xpath = new DOMXPath($dom);
//find all 'invite' nodes with username=Danielle and delete'em.
$node = $xpath->query("//invite[username='Danielle']");
// if found, append the new "value" node
if( $node->length ) {
foreach ($node as $n) {
$n->parentNode->removeChild( $n );
}
}
header('content-type: text/xml');
echo $dom->saveXML();
?>
Hope this helps.

Need to extract Sub-Tree of XML, before processing with XSLT Processor

I'm processing a XML with XSL with PHP to a HTML output. So far, so good. Here's my code.
<?php
$xslDoc = new DOMDocument();
$xslDoc->load("content.xsl");
$xmlDoc = new DOMDocument();
$xmlDoc->load("content.xml");
// some xpath/dom-query filtering to get
// subtree of loaded xml-file
$proc = new XSLTProcessor();
$proc->importStylesheet($xslDoc);
echo $proc->transformToXML($xmlDoc);
?>
Like you can see, this is a simple XSLT Processor. The output works well. For example I have in the given XML three sibling nodes "node":
<root>
<node>
<subnode>..</subnode>
</node>
<node>
<subnode>..</subnode>
</node>
<node>
<subnode>..</subnode>
</node>
</root>
Now I want just pass the second node through the XML Processor.
How can I do this?
chris
According to http://www.php.net/manual/en/xsltprocessor.transformtodoc.php, the transformToDoc method takes any DOM node as its argument so you could access $xmlDoc->getElementsByTagName('node')->item(1) and pass that to transformToDoc and then use saveXML or saveHTML to get a string of XML or HTML, depending on what kind of result you are looking for.
I solved my task by my own - but thank you for your application.
Here is my code:
$xmlDoc = new DOMDocument();
$xmlDoc->preserveWhiteSpace = false;
$xmlDoc->load("content.xml");
$xpath = new DOMXPath($xmlDoc);
$query = '//ContentData/Content[1]/Headline';
$nodeList = $xpath->query($query);
$newDom = new DOMDocument('1.0','UTF-8');
$root = $newDom->createElement('root');
$root = $newDom->appendChild($root);
foreach ($nodeList as $domElement){
$domNode = $newDom->importNode($domElement, true);
$root->appendChild($domNode);
}
$newDom->saveXML();
$xslDoc = new DOMDocument();
$xslDoc->load("content.xsl");
$proc = new XSLTProcessor();
$proc->importStylesheet($xslDoc);
echo $proc->transformToXML($newDom);

Removing a node from xml file

I have an xml file
<?xml version="1.0"?>
<category>
<name>SWEATERS</name>
<name>WATCHES</name>
<name>PANTS</name>
<name>test</name>
<name>1</name>
</category>
How i can remove the node <name>test</name> using xpath ,xquery and php. I used this code
$name='test;
$xmlfile="config/shop_categories.xml";
$xml = simplexml_load_file($xmlfile);
$target = $xml->xpath('/category[name="'.trim($name).'"]');
print_r($target[0]);
if($target == false)
return;
$domRef = dom_import_simplexml($target[0]); //Select position 0 in XPath array
$domRef->parentNode->removeChild($domRef);
$dom = new DOMDocument('1.0');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($xml->asXML());
$dom->save($xmlfile);
But it is not working.
Pretty sure this is a duplicate, but am too lazy to find it. Here you go:
$xml = <<< XML
<?xml version="1.0"?>
<category>
<name>SWEATERS</name>
<name>WATCHES</name>
<name>PANTS</name>
<name>test</name>
<name>1</name>
</category>
XML;
$dom = new DOMDocument;
$dom->loadXML($xml);
$xPath = new DOMXPath($dom);
foreach($xPath->query('//name[text() = "test"]') as $node) {
$node->parentNode->removeChild($node);
}
echo $dom->saveXML();
Output:
<?xml version="1.0"?>
<category>
<name>SWEATERS</name>
<name>WATCHES</name>
<name>PANTS</name>
<name>1</name>
</category>

Categories