I need to add a new item element to my RSS file, via PHP, without just generating the RSS from PHP. I know this will require removing older items, to match the number that I want displayed, but I don't know how to add them to the file in the first place.
My code looks somewhat like this:
<rss version="2.0">
<channel>
<title>My Site Feed</title>
<link>http://www.mysitethathasfeed.com/feed/</link>
<description>
A nice site that features a feed.
</description>
<item>
<title>Launched!</title>
<link>http://www.mysitethathasfeed.com/feed/view.php?ID=launched</link>
<description>
We just launched the site! Come join the celebration!
</description>
</item>
</channel>
</rss>
// Load the XML/RSS from a file.
$rss = file_get_cotents('path_to_file');
$dom = new DOMDocument();
$dom->loadXML($rss);
Use http://php.net/manual/en/book.dom.php to learn how to modify the dom you loaded.
Extending the answer from Kyle (oh OOP inheritence), and references from the PHP Manual
<?php
$rss = file_get_contents('feed.rss');
$dom = new DOMDocument();
$dom->loadXML($rss);
// should have only 1 node in the list
$nodeList = $dom->getElementsByTagName('channel');
// assuming there's only 1 channel tag in the RSS file:
$nChannel = $nodeList->item(0);
// now create the new item
$newNode = $dom->createElement('item');
$newNode->appendChild($dom->createElement('title', 'a new title post'));
$newNode->appendChild($dom->createElement('link', 'http://www.mysitethathasfeed.com/feed/view.php?ID=launched'));
$newNode->appendChild($dom->createElement('description', 'This is the 2nd post of our feed.'));
// add item to channel
$nChannel->appendChild($newNode);
$rss = $dom->saveXML();
file_put_contents('feed.rss', $rss);
Related
I am loading a RSS XML feed in PHP with DOMDocument. That works fine. I need to parse my XML, find specific values and then only display certain nodes again.
The XML looks like that...
<rss version="2.0">
<channel>
<title>Title</title>
<link></link>
<item>
<title>Title #1</title>
<description>Here I want to filter</description>
</item>
<item>
<title>Title #2</title>
<description>Should not be displayed</description>
</item>
</channel>
I want to search inside the description tag, and if a keyword has been found I want to display the item. If it is not found, I want to delete the parent item.
That is what I tried so far...
<?php
header('Content-Type: text/xml');
// Load our XML document
$rss = new DOMDocument();
$rss->load('https://myurl');
$description = $rss->getElementsByTagName('description');
foreach ($description as $node) {
$s = $node->nodeValue;
if (strpos($s, 'filter') !== false)
{
//found the keyword, nothing to delete
}
else
{
//didnt find it, now delete item
$node->parentNode->parentNode->removeChild($node->parentNode);
}
}
echo $description->saveXml();
I am trying to get all description nodes, check if they contain the string and if not, delete the parent. The searching for the String works, however deleting the node not. If I echo my XML, nothing has changed.
getElementsByTagName() will return a "live" result. It will change if you modify the document. You could use iterator_to_array() to make a stable copy.
Another option is to use Xpath expressions to fetch specific nodes.
$document = new DOMDocument();
$document->loadXML($xmlString);
$xpath = new DOMXpath($document);
// fetch items that contain "filter" in their description
$items = $xpath->evaluate('/rss/channel/item[contains(description, "filter")]');
foreach ($items as $item) {
// dump the title child element text content
var_dump($xpath->evaluate('string(title)', $item));
}
// fetch items that do not contain "filter" in their description
$items = $xpath->evaluate('/rss/channel/item[not(contains(description, "filter"))]');
foreach ($items as $item) {
// remove item element
$item->parentNode->removeChild($item);
}
echo $document->saveXML();
Output:
string(8) "Title #1"
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Title</title>
<link/>
<item>
<title>Title #1</title>
<description>Here I want to filter</description>
</item>
</channel>
</rss>
Hello I have xml like this:
<specs><my>base</my><root>none</root></specs>
<books>
<item>
<id>14</id>
<title>How to live</title>
</item>
<item>
...
</item>
</books>
How can I extract value from < my > ? and then < title >?
when I have data such as :<specs><my>base</my><root>none</root></specs> in xml this code works for me. So how should I modify it to work with data such as books as well in xml?
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);
$entry = $xpath->query("//xml/specs/my");
foreach($entry as $ent){
echo $ent->nodeValue;
}
simply I added this:
$xml="<xml>".$xml."</xml>";
and now this works $xpath->query("//xml/specs/my"); as well as $xpath->query("//xml/books/item");
From this tutorial - section on Adding nodes over at PHPFreaks, I did post over there but have had no replies strange as the tutorial was written by them.
http://www.phpfreaks...ndling-xml-data
When I use my xml file it creates the node but does not insert the new data. There are no page errors. I'm sure I have just missed something very simple and after hours of trying I will now bow down and ask for help.
This is the script I'm using
<?php
// isbn => pages
$page_numbers = array(
'1234' => '654', // insert data into catparent node
'5678' => '789', // insert data into catparent node
);
$dom = new DOMDocument();
$dom->load('edtest.xml');
$xpath = new DOMXPath($dom);
$items = $xpath->query('item');
foreach($items as $item)
{
$item->appendChild($dom->createElement('catparent', $page_numbers[$item->getAttribute('catcode')]));
}
$dom->save('edtest_new.xml');
?>
My XML
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<catcode>1234</catcode>
<catdesc>Systems - System Bundles</catdesc>
<price_cost>999.95</price_cost>
<price_sell>999.95</price_sell>
</item>
</items>
Output XML
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<catcode>1234</catcode>
<catdesc>Systems - System Bundles</catdesc>
<price_cost>999.95</price_cost>
<price_sell>999.95</price_sell>
<catparent></catparent> // it creates but does not insert required data
</item>
</items>
It runs the script creates the required node, but it does not insert the required data. The object of the script is to find <catcode> = 1234 and add a new <catparent> </catparent> with required data from the array.
If there is a better way to achieve the result or just the correction needed.
Thanks
You're using $item->getAttribute('catcode'). However, catcode is not an attribute of <item>, it's a child element.
Try
$catcode = $item->getElementsByTagName('catcode');
$parent_code = $page_numbers[ $catcode[0] ];
$item->appendChild( $dom->createElement('catparent', $parent_code) );
I am completely new to DOM Documents, basically what I am trying to do, is to load a RSS feed in and select only one node, and then save it to a XML file.
Here is the XML I am loading from a web feed:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Markets</title>
<description/>
<link>http://www.website.com</link>
<language>en-us</language>
<copyright>XML Output Copyright</copyright>
<ttl>15</ttl>
<pubDate>Tue, 16 Nov 2010 09:38:00 +0000</pubDate>
<webMaster>admin#website.com</webMaster>
<image>
<title>title</title>
<url>http://www.website.com/images/xmllogo.gif</url>
<link>http://www.website.com</link>
<width>144</width>
<height>16</height>
</image>
<item>
<title>title</title>
<description>the description goes here
</description>
<enclosure url="http://www.website.com/images/image.png" type="image/png"/>
</item>
</channel>
</rss>
Here is my lame attempt at getting the <description> node and saving it to feed.xml:
<?php
$feed = new DOMDocument();
$feed->load('http://www.website.com/directory/directory/cz.c');
$nodeValue = $feed->getElementsByTagName('description')->item(0)->nodeValue;
$feed->save("feed.xml");
?>
So basically I need to get the description tag, and save it as a XML file.
Any help would be appreciated, thanx in advance!
Almost correct. To get the "outerXml" of a node, you can pass the node to saveXml()
$feed = new DOMDocument();
$feed->load('http://www.website.com/directory/directory/cz.c');
$xml = $feed->saveXml($feed->getElementsByTagName('description')->item(0));
file_put_contents("feed.xml", $xml);
Saving with file_put_contents will not include an XML prolog. Note that in your example, the first description element is empty, so the file will contain <description/>.
If you want to extract the node as standalone XML Document, you have to instantiate a new DOMDocument and import the DOMNode and then use save().
$dom = new DOMDocument($feed->xmlVersion, $feed->xmlEncoding);
$dom->appendChild(
$dom->importNode(
$feed->getElementsByTagName('description')->item(0),
TRUE
)
);
echo $dom->save('new.xml');
$feed = simplexml_load_file('feed.xml');
$descr=$feed->channel->description;
Try this
I am trying to generate a Google Merchant RSS Feed, using PHP's SimpleXML and DOMDocument.
The actual generating code goes like that:
$dom = new DOMDocument('1.0', 'utf-8');
$dom->formatOutput = true;
$pRSS = $dom->createElement('rss');
$pRSS->setAttribute('version', '2.0');
$pRSS->setAttribute('xmlns:g', 'http://base.google.com/ns/1.0');
$dom->appendChild($pRSS);
$domnode = dom_import_simplexml($xml);
$domnode = $dom->importNode($domnode, true);
$domnode = $dom->appendChild($domnode);
$dom->save('googleproductfeed.xml');
($xml has all the data, but it's not relevant to my problem)
It all gets generated fine, but there is an XML error here:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2" xmlns:g="http://base.google.com/ns/1.0"/>
According to Google Merchant, Google Chrome and validome.org, there is an error in the second line.
More precisely, Validome says that it should not end with />, but just >.
The problem is I have no control over that. That part was generated by:
$pRSS = $dom->createElement('rss');
$pRSS->setAttribute('version', '2.0');
$pRSS->setAttribute('xmlns:g', 'http://base.google.com/ns/1.0');
Shouldn't <rss> be the parent element to all the contents of the feed?
It would mean that you need to append the imported XML to $pRSS, not the parent document.
$domnode = dom_import_simplexml($xml);
$domnode = $dom->importNode($domnode, true);
$domnode = $pRSS->appendChild($domnode); // Change here
Not entirely sure right now whether this won't create an extra, unnecessary node under <rss>, but it's the right direction in any case.
You should add other nodes as children to $pRSS