i want to remove g:price=0 OR out of stock OR no image ITEMS from my Google Merchant xml feed by PHP.
i'm trying for hours and hours; but could not find a solution yet..
example: (if i have xml like this; the new xml must list only the second item)
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title><![CDATA[example title]]></title>
<link><![CDATA[http://www.example.com]]></link>
<description><![CDATA[example description]]></description>
<item>
<g:additional_image_link><![CDATA[]]></g:additional_image_link>
<g:image><![CDATA[]]></g:image>
<g:availability><![CDATA[out of stock]]></g:availability>
<g:price>0.00 TRY</g:price>
</item>
<item>
<g:image><![CDATA[http://www.example.com/image.jpg]]></g:image>
<g:availability><![CDATA[in stock]]></g:availability>
<g:price>100.00 TRY</g:price>
</item>
</channel>
</rss>
Could someone help me? Expected output is this:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title><![CDATA[example title]]></title>
<link><![CDATA[http://www.example.com]]></link>
<description><![CDATA[example description]]></description>
<item>
<g:image><![CDATA[http://www.example.com/image.jpg]]></g:image>
<g:availability><![CDATA[in stock]]></g:availability>
<g:price>100.00 TRY</g:price>
</item>
</channel>
</rss>
Here we are using DOMDocument for extracting nodes and removing un-required nodes.
Try this code snippet here
<?php
ini_set('display_errors', 1);
libxml_use_internal_errors(true);
$string = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title><![CDATA[example title]]></title>
<link><![CDATA[http://www.example.com]]></link>
<description><![CDATA[example description]]></description>
<item>
<g:additional_image_link><![CDATA[]]></g:additional_image_link>
<g:image><![CDATA[]]></g:image>
<g:availability><![CDATA[out of stock]]></g:availability>
<g:price>0.00 TRY</g:price>
</item>
<item>
<g:image><![CDATA[http://www.example.com/image.jpg]]></g:image>
<g:availability><![CDATA[in stock]]></g:availability>
<g:price>100.00 TRY</g:price>
</item>
</channel>
</rss>
XML;
$array = array("g:image", "g:price", "g:availability");
$domObject = new DOMDocument();
$domObject->loadXML($string);
$results = $domObject->getElementsByTagName("item");
$nodesToRemove = array();
foreach ($results as $node)
{
foreach ($node->childNodes as $innerNode)
{
if ($innerNode instanceof DOMElement && in_array($innerNode->tagName, $array))
{
if ($innerNode->tagName == "g:image" && empty($innerNode->textContent))
{
$nodesToRemove[] = $innerNode->parentNode;
break;
} elseif ($innerNode->tagName == "g:price" && preg_match("/\b0+(\.[0]+)\b/", $innerNode->textContent))
{
$nodesToRemove[] = $innerNode->parentNode;
break;
} elseif ($innerNode->tagName == "g:availability" && $innerNode->textContent == "out of stock")
{
$nodesToRemove[] = $innerNode->parentNode;
break;
}
}
}
}
foreach ($nodesToRemove as $node)
{
$node->parentNode->removeChild($node);
}
echo $domObject->saveXML();
Output:
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title><![CDATA[example title]]></title>
<link><![CDATA[http://www.example.com]]></link>
<description><![CDATA[example description]]></description>
<item>
<g:image><![CDATA[http://www.example.com/image.jpg]]></g:image>
<g:availability><![CDATA[in stock]]></g:availability>
<g:price>100.00 TRY</g:price>
</item>
</channel>
</rss>
Related
This question already has answers here:
Simple XML - Dealing With Colons In Nodes
(4 answers)
Closed 5 years ago.
This is may xml file
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title>werwer</title>
<link>werwerwe</link>
<item>
<g:id>704667</g:id>
<title>Nike</title>
<description>erterterter</description>
</item>
<item>
<g:id>4456456</g:id>
<title>Nike</title>
<description>erterterter</description>
</item>
</channel></rss>
how to parse that xml file, I have script but it doesnt work
if (file_exists('products.xml')) {
$xml = simplexml_load_file('products.xml');
print_r($xml);
} else {
exit('Failed to open products.xml.');
}
any idea how to get information between g:id?
You need to get an apply the namespace to the children. http://php.net/manual/en/simplexmlelement.getnamespaces.php
<?php
$xml = '<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title>werwer</title>
<link>werwerwe</link>
<item>
<g:id>704667</g:id>
<title>Nike</title>
<description>erterterter</description>
</item>
<item>
<g:id>4456456</g:id>
<title>Nike</title>
<description>erterterter</description>
</item>
</channel>
</rss>';
$xml = simplexml_load_string($xml);
$ns = $xml->getNamespaces(true);
foreach ($xml->channel->item as $item) {
echo $item->children($ns['g'])->id.PHP_EOL;
}
/*
704667
4456456
*/
https://3v4l.org/t2D84
i facing few issue's i don't know how to resolve it
i want to write following rss feed using php and mysql:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<item>
<title>Here is the title</title>
<link>http://example.com</link>
<media:content medium="image" url="http://example.com/image.jpg"></media:content>
<media:content medium="video" url="http://example.com/video.mp4"></media:content>
</item>
</channel>
</rss>
here is my code in php:
$db = new Db();
$result = $db->select("select * from column");
$xml = new SimpleXMLElement('<channel/>');
for ($i = 0; $i < count($result); $i++) {
$title = $result[$i]title
$link = $result[$i]['link'];
$image = $result[$i]['image'];
$video = $result[$i]['video'];
$item = $xml->addChild('item');
$item->title = $title
$item->link = $link
$item->image = ?? ;
$item->video = ?? ;
}
Header('Content-type: text/xml');
print($xml->asXML());
just don't know how to set image and video because there tags are different like media:content and url of both image and video tags. please let me know
thanks
You can not do that. Your XML is not valid. Prefixed tags must have a declared NameSpace URI, in your case 'http://search.yahoo.com/mrss/':
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
(...)
</rss>
You can use ->addChild to create namespaced elements:
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
<channel/>
</rss>');
(...)
$item = $xml->channel->addChild('item');
$item->title = $title;
$item->link = $link;
/* Add <media:image>: */
$node = $item->addChild( 'image', Null, 'http://search.yahoo.com/mrss/' );
$node->addAttribute( 'url', $image );
/* Add <media:video>: */
$node = $item->addChild( 'video', Null, 'http://search.yahoo.com/mrss/' );
$node->addAttribute( 'url', $video );
Result:
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<item>
<title>Your Title</title>
<link>http://www.somelink.it/</link>
<media:image url="http://www.image.com/"/>
<media:video url="http://www.video.com/"/>
</item>
</channel>
</rss>
I need your help once again!
I need to read this xml file... but the problem is that it's not working!
This is the XML
<rss xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<item>
<title>Video</title>
<media:content url="http://videourl.com/etc/" type="video/x-flv" duration="5128"/>
</item>
</channel>
</rss>
And this is my code:
<?php
$xml=simplexml_load_file("http://videourl.com/etc/");
echo $xml->getName() . "<media:content url=";
foreach($xml->children() as $child)
{
echo $child->getName() . ": " . $child . "";
}
?>
And it's not working! It's not working because nothing gets echoed, or printed! Does anyone spot the error?
<?php
$xml = '<?xml version="1.0" encoding="UTF-8" ?>
<rss>
<channel>
<item>
<title><![CDATA[Tom & Jerry]]></title>
</item>
</channel>
</rss>';
$xml = simplexml_load_string($xml);
// echo does the casting for you
echo $xml->channel->item->title;
// but vardump (or print_r) not!
var_dump($xml->channel->item->title);
// so cast the SimpleXML Element to 'string' solve this issue
var_dump((string) $xml->channel->item->title);
?>
Again i edit my code now try this
May be the question is already answered in a way or in another in many questions, but since I'm a new bie in XML, I can't figured it out in my project.
I have an RSS (XML) file with this structure:
<rss>
<channel>
<item>
<title>some title</title>
<description> some descrp </description>
...
</item>
</channel>
</rss>
How can I, in PHP, delete some item when the title is equal to some value? THanks.
EDIT1 : I have my XML file stored at my web server.
$rss = "
<rss>
<channel>
<item>
<title>some title</title>
<description> some descrp </description>
</item>
<item>
<title>some other title</title>
<description> some descrp </description>
</item>
</channel>
</rss>
";
$doc = new DOMDocument();
$doc->loadXML($rss);
$xpath = new DOMXPath($doc);
$els = $xpath->query('//title[text()="some title"]');
foreach($els as $el)
{
$parent = $el->parentNode;
$parent->parentNode->removeChild($parent);
}
echo $doc->saveXML();
It searches for exact match.
ps: another method, without xpath
$doc = new DOMDocument();
$doc->loadXML($rss);
$els = $doc->getElementsByTagName('title');
for($i = $els->length-1; $i >= 0; $i--)
{
$el = $els->item($i);
if ($el->nodeValue == 'some title')
{
$parent = $el->parentNode;
$parent->parentNode->removeChild($parent);
}
}
echo $doc->saveXML();
I am trying to reformat XML adding intermediate level node.
Here is what I have as input:
<channel>
<item>
<title>Advanced PHP Book</title>
</item>
<item>
<title>MySQL primer</title>
</item>
<item>
<title>C++ for beginners</title>
</item>
</channel>
I need it to be like that at the end (page node added between channel and item):
<channel>
<page>
<item>
<title>Advanced PHP Book</title>
</item>
<item>
<title>MySQL primer</title>
</item>
<item>
<title>C++ for beginners</title>
</item>
</page>
</channel>
Here is my testing code:
$sxe = simplexml_load_string($string);
$dom_sxe = dom_import_simplexml($sxe);
$dom = new DOMDocument('1.0');
$channel = $dom->appendChild($dom->createElement('channel'));
$page = $channel->appendChild($dom->createElement('page'));
$dom_sxe = $dom->importNode($dom_sxe, true);
$dom_sxe = $page->appendChild($dom_sxe);
$dom->formatOutput = true;
echo $dom->saveXML();
The problem I have is that channel element is doubled.
Please help.
I don't think this should be too hard: I think you're overcomplicating it by using the simplexml stuff.
$dom = new DOMDocument;
$dom->loadXML($string);
// create the <page> element
$page = $dom->createElement('page');
while ($dom->firstChild->firstChild) {
// move the items in <channel> to the <page> element
$page->appendChild($dom->firstChild->firstChild);
}
// insert the <page> element into <channel>
$dom->firstChild->appendChild($page);
$dom->saveXML();
$xml = '<channel> <item> <title>Advanced PHP Book</title> </item> <item> <title>MySQL primer</title> </item> <item> <title>C++ for beginners</title> </item> </channel>';
$dom = new DOMDocument;
$dom->loadXML($xml);
$page = $dom->createElement('page');
$items = $dom->getElementsByTagName('item');
while ($items->length) {
$page->appendChild($items->item(0));
}
$dom->getElementsByTagName('channel')->item(0)->appendChild($page);
echo $dom->saveXML();
Output
<?xml version="1.0"?>
<channel> <page><item> <title>Advanced PHP Book</title> </item><item> <title>MySQL primer</title> </item><item> <title>C++ for beginners</title> </item></page></channel>
See it.