XPATH Get Multiple Values within same Element in an RSS Feed - php

I have an rss feed that is formatted something like this:
<item>
<posturl>mysite.com/abc.html</posturl>
<imagepath>123.jpg</imagepath>
</item>
<item>
<posturl>mysite.com/def.html</posturl>
<imagepath>456.jpg</imagepath>
</item>
<item>
<posturl>mysite.com/ghi.html</posturl>
<imagepath>789.jpg</imagepath>
</item>
I have a script where I want to extract both the values above. I can extract one of the values and build html code using code like:
<?php
$xml = simplexml_load_file('http://myrssfeed.com');
$imgs = $xml->xpath('//imagepath');
echo '<ul>';
foreach($imgs as $output1) {
echo '<li><img src="' . $output1 . '" ></li>';
}
echo '</ul>';
?>
This works like a charm thanks to all the help from people here. But I need to expand that second echo line to read something like:
echo '<li><img src="' . $output1 . '" ></li>';
I need help on how to extract $output2 = posturl within the same item as $output1.
Basically I need to display the images as links... both imagepath and posturl are elements within item.
Many thanks.

You could select the <item> elements instead of <posturl> and <imagepath>. Like this:
$xml = simplexml_load_file('http://myrssfeed.com');
echo '<ul>';
foreach($xml->xpath('//item') as $item) {
printf('<li><img src="%s" /></li>',
$item->posturl, $item->imagepath);
}
echo '</ul>';

Related

Simplexml : xpath with three conditions

I have a xml file like this :
<rss version="2.0" xmlns:atom="https://www.w3.org/2005/Atom">
<channel>
<item>
<city>London</city>
<description>Trip</description>
<link>page.php</link>
<img>img.jpg</img>
</item>
<item>
<city>London</city>
<description>Trip</description>
<link>page.php</link>
<img>img.jpg</img>
</item>
<item>
<city>Paris</city>
<description>Trip</description>
<link>page.php</link>
<img>img.jpg</img>
</item>
.
.
</channel>
</rss>
If I want to select TRIP in LONDON, I do that :
<?php
$xml = simplexml_load_file('file.xml');
$items = $xml->xpath('//item[city[contains(.,"London")] and description[contains(.,"Trip")]]');
foreach($items as $item){
echo ' txt ';
}
?>
If I want to select ONLY the first TRIP in LONDON, I do that :
<?php
$xml = simplexml_load_file('file.xml');
$items = $xml->xpath('//item[city[contains(.,"London")] and description[contains(.,"Trip")]]')[0];
foreach($items as $item){
echo ' txt ';
}
?>
I try also 1 instead of 0, and this
[position()=0]
it does not work.
What's wrong ?
I keep looking.
I have made several tests only with the position filter, for example :
<?php
$xml = simplexml_load_file('site-alpha.xml');
$items = $xml->xpath('//(/item)[1]');
foreach($xml->channel->item as $item){
echo '<div>....</div>';
}
?>
And it doesn't work.
I think I have a problem with this part, but I don't see where.
<?php
// Load the XML file
$xml = simplexml_load_file('your_xml_file.xml');
// Iterate through each "item" element
foreach ($xml->item as $item) {
// Output the description and city
echo $item->description . ' in ' . $item->city . '<br>';
}
?>
Unlike php, xpath indexing start from "1".
So either of these should get you only the first trip:
#indexing is indicated inside the xpath expression so it starts with 1:
$items = $xml->xpath('//item[city[contains(.,"London")] and description[contains(.,"Trip")]][1]');
or
#indexing is indicated outside the xpath expression so it's handled by php and starts with 0:
$items = $xml->xpath('//item[city[contains(.,"London")] and description[contains(.,"Trip")]]')[0];

nested foreach loop in PHP 5

So here is the deal:
I have an array that contains manufacturers' names for smartphones and an XML file that holds specifications for each specific phone.
What I am trying to do is to group phones based on manufacturer. I am using nested FOREACH loop to do this. And here is my code:
foreach ($makes as $manufacturer){
echo '<div>'.'<h2>'.$manufacturer.'</h2>'.'<hr>';
foreach ($xml as $item){
if($item->make == $manufacturer){
$src = $item->thumb;
echo '<div>'."<img src='$src' width='100'/>".'<h1>'.
$item->make.' '.$item->model.'</h1>'.'</div>';
}
}
echo '</div>';
}
The problem with this approach is that for some reason my page displays ONLY THE FIRST phone for every manufacturer, instead of going through every model.
What am I doing wrong here?
Here is XML sample:
<?xml version="1.0" encoding="utf-8"?>
<items>
<item>
<make></make>
<model></model>
<thumb></thumb>
</item>
</items>
Also, if I remove outer loop, code works perfectly and displays every phone from the XML
You have a typo:
echo '<div>'."<img src='$src' width='100'/>".'<h1>'.
$item->make.' '.$item->model.'</h1>'.
should be
echo '<div>'."<img src='$src' width='100'/>".'<h1>'.
$item->make.' '.$item->model.'</h1>';
Note the ";" at the end of the echo.

how to get the values from this xml using dom in php?

how can i get the values of a,b and c from the following xml code?
<result name="response" f="139" c="0">
−
<doc score="5.06756" pos="0">
<snippet name="a" highlighted="yes">example</snippet>
<snippet name="b" highlighted="yes">bexample</snippet>
<snippet name="c">cexample</snippet>
</doc>
</result>
I tried to print the nodes, but It failed:
$xmlDoc = new DOMDocument();
$xmlDoc->load($content);
$x = $xmlDoc->documentElement;
foreach ($x->childNodes AS $item)
{
print $item->nodeName . " = " . $item->nodeValue . "<br />";
}
Can anyone tell me how I can parse it? I cannot use simple xml, so I am moving to Dom.
Using DOM allows you to use several distinct ways of extracting informations.
For example, you could work with :
DOMDocument::getElementsByTagName, to extract all tags having a specific name.
Or DOMXPath, for more complex queries.
As an example, here's a portion of code that demonstrates how to use the first solution to extract all <snippet> tags :
$snippets = $xmlDoc->getElementsByTagName('snippet');
foreach ($snippets as $tag) {
echo $tag->getAttribute('name') . ' = ' . $tag->nodeValue . '<br />';
}
And you'd get this output :
a = example
b = bexample
c = cexample
And, as another example, here's a solution that demonstrates how to use the second solution, to do a more complex query on the XML data -- here, extracting the <snippet> tag that as it's name attribute with a value of a :
$xpath = new DOMXPath($xmlDoc);
$snippetsA = $xpath->query('//snippet[#name="a"]');
if ($snippetsA->length > 0) {
foreach ($snippetsA as $tag) {
echo $tag->getAttribute('name') . ' = ' . $tag->nodeValue . '<br />';
}
}
Which only gets you one result -- the corresponding tag :
a = example
Starting from here, the possibilities are almost limitless ;-)

PHP SimpleXML XPath get next parent node

I've never asked a question here before so please forgive my question if its formatted badly or not specific enough. I am just a dabbler and know very little about PHP and XPath.
I have an XML file like this:
<catalogue>
<item>
<reference>A1</reference>
<title>My title1</title>
</item>
<item>
<reference>A2</reference>
<title>My title2</title>
</item>
</catalogue>
I am pulling this file using SimpleXML:
$file = "products.xml";
$xml = simplexml_load_file($file) or die ("Unable to load XML file!");
Then I am using the reference from a URL parameter to get extra details about the 'item' using PHP:
foreach ($xml->item as $item) {
if ($item->reference == $_GET['reference']) {
echo '<p>' . $item->title . '</p>';
}
So from a URL like www.mysite.com/file.php?reference=A1
I would get this HTML:
<p>My title1</p>
I realise I might not be doing this right and any pointers to improving this are welcome.
My question is, I want to find the next and previous 'item' details. If I know from the URL that reference=A1, how do I find the reference, title etc of the next 'item'? If I only have 'A1' and I know that's a reference node, how do I get HTML like this:
<p>Next item is My title2</p>
I have read about following-sibling but I don't know how to use it. I can only find the following-sibling of the reference node, which isn't what I need.
Any help appreciated.
You could use:
/catalogue/item[reference='A1']/following-sibling::item[1]/title
Meaning: from an item element child of catalogue root element, having a reference element with 'A1' string value, navegate to first following sibling item element's title child.
I´d probably use xpath to fetch the next/previous (and current) node.
<?php
error_reporting(E_ALL ^ E_NOTICE);
$s = '
<catalogue>
<item>
<reference>A1</reference>
<title>My title1</title>
</item>
<item>
<reference>A2</reference>
<title>My title2</title>
</item>
<item>
<reference>A3</reference>
<title>My title3</title>
</item>
</catalogue>
';
$xml = simplexml_load_string($s);
$reference = 'A3';
list($current) = $xml->xpath('/catalogue/item[reference="' . $reference . '"]');
if($current) {
print 'current: ' . $current->title . '<br />';
list($prev) = $current->xpath('preceding-sibling::*[1]');
if($prev) {
print 'prev: ' . $prev->title . '<br />';
}
list($next) = $current->xpath('following-sibling::*[1]');
if($next) {
print 'next: ' . $next->title . '<br />';
}
}
See the documentation of SimpleXMLElement::xpath and XPath syntax documentation.

Extracting Certain XML Elements with PHP SimpleXML

I am having some problems parsing this piece of XML using SimpleXML. There is always only one Series element, and a variable number of Episode elements beneath. I want to parse XML so I can store the Series data in one table, and all the Episode data in another table.
XML:
<Data>
<Series>
<id>80348</id>
<Genre>|Action and Adventure|Comedy|Drama|</Genre>
<IMDB_ID>tt0934814</IMDB_ID>
<SeriesID>68724</SeriesID>
<SeriesName>Chuck</SeriesName>
<banner>graphical/80348-g.jpg</banner>
</Series>
<Episode>
<id>935481</id>
<Director>Robert Duncan McNeill</Director>
<EpisodeName>Chuck Versus the Third Dimension 2D</EpisodeName>
<EpisodeNumber>1</EpisodeNumber>
<seasonid>27984</seasonid>
<seriesid>80348</seriesid>
</Episode>
<Episode>
<id>935483</id>
<Director>Robert Duncan McNeill</Director>
<EpisodeName>Buy More #15: Employee Health</EpisodeName>
<EpisodeNumber>2</EpisodeNumber>
<seasonid>27984</seasonid>
<seriesid>80348</seriesid>
</Episode>
</Data>
When I attempt to access just the first Series element and child nodes, or iterate through the Episode elements only it does not work. I have also tried to use DOMDocument with SimpleXML, but could not get that to work at all.
PHP Code:
<?php
if(file_exists('en.xml'))
{
$data = simplexml_load_file('en.xml');
foreach($data as $series)
{
echo 'id: <br />' . $series->id;
echo 'imdb: <br />' . $series->IMDB_ID;
}
}
?>
Output:
id:80348
imdb:tt0934814
id:935481
imdb:
id:1534641
imdb:
I just discovered the stupid mistake I was making.
The PHP code should have been like this:
<?php
if(file_exists('en.xml'))
{
$data = simplexml_load_file('en.xml');
foreach($data->Series as $series)
{
echo 'id: <br />' . $series->id;
echo 'imdb: <br />' . $series->IMDB_ID;
}
}
?>
The first time I tried this (and it did not work) I was using;
$data->series as $series
So it was a capital 'S' that was the issue.

Categories