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
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>
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
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.
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);
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>