read xml using file get contents - php

i hv a xml file,how to get values in title field using get file content method..i just want to get the value "TomTom XXL 550M - US, Canada & Mexico Automotive GPS. (Brand New)"
<Title>
TomTom XXL 550M - US, Canada & Mexico Automotive GPS. (Brand New)
</Title>
my code
$xmlstr = file_get_contents($source);
$parseXML = new SimpleXMLElement($xmlstr);
print($parseXML);
// load as file
$parseXMLFile = new SimpleXMLElement($source,null,true);

If you feel confortable with javascript, there is another solution called DOMDocument
You can load XML files and also use function like getElementsByTagName. For example, if you have a books.xml file like this:
<?xml version="1.0" encoding="utf-8"?>
<books>
<book><title>Patterns of Enterprise Application Architecture</title></book>
<book><title>Design Patterns: Elements of Reusable Software Design</title></book>
<book><title>Clean Code</title></book>
</books>
You can extract titles so:
$dom = new DOMDocument;
$dom->load('books.xml');
$books = $dom->getElementsByTagName('title');
foreach ($books as $book) {
echo $book->nodeValue.'<br>';
}

You just have to read your file with simplexml_load_file : Doc for this one
You will then get object of class SimpleXMLElement.
Then, you can use it to get what you want ! Some examples here : SimpleXML Examples

Related

Check if child exists? - SimpleXML (PHP)

I have different XML files where I renamed for each XML file all individual tags, so that every XML file has the same tag name. That was easy because the function was customized for the XML file.
But instand of writing 7 new functions for each XML file now I want to check if a XML file has a specidifed child or not. Because if I want to say:
foreach ($items as $item) {
$node = dom_import_simplexml($item);
$title = $node->getElementsByTagName('title')->item(0)->textContent;
$price = $node->getElementsByTagName('price')->item(0)->textContent;
$url = $node->getElementsByTagName('url')->item(0)->textContent;
$publisher = $node->getElementsByTagName('publisher')->item(0)->textContent;
$category = $node->getElementsByTagName('category')->item(0)->textContent;
$platform = $node->getElementsByTagName('platform')->item(0)->textContent;
}
I get sometimes: PHP Notice: Trying to get property of non-object in ...
For example. Two different XML sheets. One contains publisher, category and platform, the other not:
XML 1:
<products>
<product>
<desc>This is a Test</desc>
<price>11.69</price>
<price_base>12.99</price_base>
<publisher>Stackoverflow</publisher>
<category>PHP</category>
</packshot>
<title>Check if child exists? - SimpleXML (PHP)</title>
<url>http://stackoverflow.com/questions/ask</url>
</product>
</products>
XML 2:
<products>
<product>
<image></image>
<title>Questions</title>
<price>23,90</price>
<url>google.de/url>
<platform>Stackoverflow</platform>
</product>
</products>
You see, sometimes one XML file contains publisher, category and platform but sometimes not. But it could also be that not every node of a XML file contains all attributes like in the first!
So I need to check for every node of a XML file individual if the node is containing publisher, category or/and platform.
How can I do that with SimpleXML?
I thought about switch case but at first I need to check which childs are contained in every node.
EDIT:
Maybe I found a solution. Is that a solution or not?
if($node->getElementsByTagName('platform')->item(0)){
echo $node->getElementsByTagName('platform')->item(0)->textContent . "\n";
}
Greetings and Thank You!
One way to rome... (working example)
$xml = "<products>
<product>
<desc>This is a Test</desc>
<price>11.69</price>
<price_base>12.99</price_base>
<publisher>Stackoverflow</publisher>
<category>PHP</category>
<title>Check if child exists? - SimpleXML (PHP)</title>
<url>http://stackoverflow.com/questions/ask</url>
</product>
</products>";
$xml = simplexml_load_string($xml);
#set fields to look for
foreach(['desc','title','price','publisher','category','platform','image','whatever'] as $path){
#get the first node
$result = $xml->xpath("product/{$path}[1]");
#validate and set
$coll[$path] = $result?(string)$result[0]:null;
#if you need here a local variable do (2 x $)
${$path} = $coll[$path];
}
#here i do array_filter() to remove all NULL entries
print_r(array_filter($coll));
#if local variables needed do
extract($coll);#this creates $desc, $price
Note </packshot> is an invalid node, removed here.
xpath syntax https://www.w3schools.com/xmL/xpath_syntax.asp
Firstly, you're over-complicating your code by switching from SimpleXML to DOM with dom_import_simplexml. The things you're doing with DOM can be done in much shorter code with SimpleXML.
Instead of this:
$node = dom_import_simplexml($item);
$title = $node->getElementsByTagName('title')->item(0)->textContent;
you can just use:
$title = (string)$item->title[0];
or even just:
$title = (string)$item->title;
To understand why this works, take a look at the SimpleXML examples in the manual.
Armed with that knowledge, you'll be amazed at how simple it is to see if a child exists or not:
if ( isset($item->title) ) {
$title = (string)$item->title;
} else {
echo "There is no title!";
}

Get data (zip code) from xml (maps api) and create url

I have created a android app that gets the gpslocation and creates a url:
https://maps.googleapis.com/maps/api/geocode/xml?latlng=00.00,00.00&sensor=true
Example:
https://maps.googleapis.com/maps/api/geocode/xml?latlng=42.120636,-72.568731&sensor=true
This returns (only a part):
<GeocodeResponse>
<status>OK</status>
<result>
<type>street_address</type>
<formatted_address>
17 Dorchester Street, Springfield, Massachusetts 01109, United States
</formatted_address>
<address_component>
<long_name>17</long_name>
<short_name>17</short_name>
<type> ...
And i'm interested in this part: 17 Dorchester Street, Springfield, Massachusetts 01109, United States.
And I would like to create a new url that contains the zip number code "01109" like
http://mysite.com?process=01109 and open this site.
Can anyone help me!
So, the XML you link to actually has the postal code in it. It is an address_component with a child type that has the value postal_code. The easiest way to get there, IMHO, is XPath:
$d = <<<HER
<GeocodeResponse>
<!-- yada... -->
<result>
<!-- yada -->
<address_component>
<long_name>01109</long_name>
<short_name>01109</short_name>
<type>postal_code</type>
</address_component>
<!-- yada -->
</result>
<!-- yoda -->
</GeocodeResponse>
HER;
$doc = new DomDocument();
$doc->loadXML($d);
$path = new DomXPath($doc);
/*
the query translates->
// = all nodes
address_component = which have the type of 'address_component'
type = the children of the address_component with the type 'type'
[text() = "postal_code"] = but only the type's with the value 'postal_code'
/preceding-sibling = all nodes before this one in the same parent
::*[1] = the one most adjacent of the sibling
*/
$p = $path->query(
'//address_component/type[text() = "postal_code"]/preceding-sibling::*[1]');
$newUrl = 'http://mysite.com?process='.$p->item(0)->nodeValue;
print($newUrl);
To obtain specific data from the googleapis geocode response you not only need to locate an element by it's name but also by it's content.
This can be easily done with Xpath. Luckily the SimpleXML extension in PHP has good support for reading such common formatted XML documents.
First for the Xpath:
<GeocodeResponse>
<result>
<type>street_address</type>
The <result> element is the element that has a child <type> which node-value is street_address. In Xpath this is expressed as:
/*/result/type[. = "street_address"]/..
And it works similar for the ZIP-code. It is the <address_component> child of the previous <result> node that has a child <type> which node-value is postal_code and of that element you want:
address_component/type[. = "postal_code"]/..
So far for the xpaths. All you need to get this to run is to load the XML document, execute the paths and read out the values you're interested in:
$xml = simplexml_load_file($xmlFile);
list($result) = $xml->xpath('/*/result/type[. = "street_address"]/..');
list($postal_code) = $result->xpath('address_component/type[. = "postal_code"]/..');
echo $result->formatted_address, "\nZIP: ", $postal_code->long_name, "\n";
With the XML documented linked in your question this creates the following output:
17 Dorchester Street, Springfield, MA 01109, USA
ZIP: 01109
I hope this is helpful.
You can access the postal_code short_name using simplexml and xpath. Here's a working example:
$location = simplexml_load_file('https://maps.googleapis.com/maps/api/geocode/xml?latlng=42.120636,-72.568731&sensor=true');
$postal_code_search =
$location->xpath('//result[type="street_address"]/address_component[type="postal_code"]/short_name');
$postal_code = (string) $postal_code_search[0];
Notice that you must cast the values to string explicitly, as simplexml will return array or object to variables versus a string when printed (which can be confusing when testing).

PHP - Retrieving Only Certain XML Nodes and Saving to a file

I am using PHP curl to retrive an xml file from a remote url and save it to a local file on my server. The structure is the following:
<Store Country="Ireland">
<EventsPoints>
<Event ID="1800" >
<ArtistIDs>
<ArtistID ID="109" Type="Primary" />
</ArtistIDs>
<CategoryID>1</CategoryID>
<Country>IRL</Country>
<PerformanceName>Music and Arts</PerformanceName>
<VenueID ID="197" />
</Event>
<Venues>
<Venue ID="197">
<City>Dublin</City>
<Country>IRL</Country>
<VenueName>ABC</VenueName>
<VenueNumber>22</VenueNumber>
</Venue>
</Venues>
The above xml blocks are stored in the same XML file. There are several Event blocks and several Venue blocks.
The problem i'm having is using PHP to access this large XML file and iterate through the Venue blocks retrieving only a Venue block with a certain ID specified via a parameter.
I then want to iterate through the event blocks - only retrieving the events matching this specified venue ID. I then want to save this to a file on the server.
I want to do this for each venue.
How do I go about doing the above?
EDIT:
For each Venue and events related to that venue, I just want to literally copy them to their own file - basically splitting down the larger file into individual files
$docSource = new DOMDocument();
$docSource->loadXML($xml);
$docDest = new DOMDocument();
$docDest->loadXML(file_get_contents('/var/www/html/xml/testfile.xml'));
$xpath = new DOMXPath($docSource);
$id = "197";
$result = $xpath->query('//Event/VenueID[#ID=$id]')->item(0); //Get directly the node you want
$result = $docDest->importNode($result, true); //Copy the node to the other document
$items = $docDest->getElementsByTagName('items')->item(0);
$items->appendChild($result); //Add the copied node to the destination document
echo $docDest->saveXML();
You are not showing the desired output format, so I will assume this generates what you want. If not, feel free to modify the code so it meets the desired output format. This along with the comments above should have all you need to get this working on your own.
// load Source document
$srcDom = new DOMDocument;
$srcDom->load('/var/www/html/xml/testfile.xml');
$xPath = new DOMXPath($srcDom);
// iterate over all the venues in the source document
foreach ($srcDom->getElementsByTagName('Venue') as $venue) {
// create a new destination document for the current venue
$dstDom = new DOMDocument('1.0', 'utf-8');
// add an EventsPoint element as the root node
$dstDom->appendChild($dstDom->createElement('EventsPoint'));
// import the Venue element tree to the new destination document
$dstDom->documentElement->appendChild($dstDom->importNode($venue, true));
// fetch all the events for the current venue from the source document
$allEventsForVenue = $xPath->query(
sprintf(
'/Store/EventsPoints/Event[VenueID/#ID=%d]',
$venue->getAttribute('ID')
)
);
// iterate all the events found in Xpath query
foreach ($allEventsForVenue as $event) {
// add event element tree to current destination document
$dstDom->documentElement->appendChild($dstDom->importNode($event, true));
}
// make output prettier
$dstDom->formatOutput = true;
// save XML to file named after venue ID
$dstDom->save(sprintf('/path/to/%d.xml', $venue->getAttribute('ID')));
}
This will create an XML file like this
<?xml version="1.0" encoding="utf-8"?>
<EventsPoint>
<Venue ID="197">
<City>Dublin</City>
<Country>IRL</Country>
<VenueName>ABC</VenueName>
<VenueNumber>22</VenueNumber>
</Venue>
<Event ID="1800">
<ArtistIDs>
<ArtistID ID="109" Type="Primary"/>
</ArtistIDs>
<CategoryID>1</CategoryID>
<Country>IRL</Country>
<PerformanceName>Music and Arts</PerformanceName>
<VenueID ID="197"/>
</Event>
</EventsPoint>
in the file 197.xml

How to parse a specific xml file using PHP simpleXML

I know there is already a lot of topics about simpleXML and PHP, but I need help with an specific xml code.
<vitrine>
<canal>Hotwords</canal>
<product id="0">
<descricao>MP3 Apple iPod Class...</descricao>
<loja>ApetreXo.com</loja>
<preco>à vista R$765,22</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/18/80x80_107156_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=BiY4C2UnHQ0LOWgyGjc3NRFp-</urlProduto>
</product>
<product id="1">
<descricao>TV Sony Bravia 3D LE...</descricao>
<loja>Fast Shop.com.b...</loja>
<preco>10 x R$299,90</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/2852/80x80_319373_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=JDEn-</urlProduto>
</product>
</vitrine>
I need a foreach to get the data from each "product" like this:
<?
$feedUrl = 'url to xml file';
$rawFeed = file_get_contents($feedUrl);
$xml = simplexml_load_string($rawFeed);
foreach ($item ...????? ?)
{
}
How can I do this foreach to get the data. I tried all that I know without success.
Thanks.
First, you need <?xml version="1.0" encoding="UTF-8"?> as the first line in your XML, otherwise it's not valid. Then, and this will help you debug all sorts of things over your coding career, try this line:
echo "<pre>".print_r($xml,true)."</pre>";
That will give you the exact layout of the object you get back from the simplexml_load_string() call. From there, since you have a visual of the object layout, you should be able to figure out how to parse it. Incidentally, in your case, I think you'd need to do something like:
foreach($xml->vitrine as $element) {
// your code goes here
}
It seems PHP gets rid of evrything after the whitespace, because product id was changed to just product. Anyway here's the code.
<?php
$v = <<<ABC
<vitrine>
<canal>Hotwords</canal>
<product id="0">
<descricao>MP3 Apple iPod Class...</descricao>
<loja>ApetreXo.com</loja>
<preco>à vista R$765,22</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/18/80x80_107156_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=BiY4C2UnHQ0LOWgyGjc3NRFp-</urlProduto>
</product>
<product id="1">
<descricao>TV Sony Bravia 3D LE...</descricao>
<loja>Fast Shop.com.b...</loja>
<preco>10 x R$299,90</preco>
<urlImagem>http://imagem.domain.com.br/thumbs/ensopado/2852/80x80_319373_1.jpg</urlImagem>
<urlProduto>http://domain.com.br/tr/rd?o=JDEn-</urlProduto>
</product>
</vitrine>
ABC;
$xml = simplexml_load_string($v);
//print_r($xml);
foreach ($xml->product as $c){
echo $c->loja; //echoing out value of 'loja'
}
Outputs
ApetreXo.com
Fast Shop.com.b...

Filter a RSS flux by keywords in PHP

I have a little site in PHP (that is more static that dynamic, anyway). I see multiple sites publishes RSS fluxes or whatever the name is.
I wonder if there a possibility to load a such RSS flux, filter it by the site keywords theme and display it like a little thematic news column using PHP.
Is this task complicated? With what should I start? I am completely new in the field, so sorry if such a questions are already answered.
Update: There were a few errors in this answer's code. Thanks to #obelizsk for identifying them, I've updated the answer since.
Given a RSS:
<rss version="2.0">
<channel>
<title>(Title)</title>
<description>(Description)</description>
<link>http://www.link.to/the/feed/</link>
<item>
<title> New RSS Creation Tool </title>
<description> FeedForAll generates rss feeds so webmasters do not need to struggle with feed creation </description>
<link> http://www.feedforall.com </link>
<pubDate> Aug, 22 2004 00:12:30 EST </pubDate>
<category> software </category>
</item>
</channel>
</rss>
You could scan the title, description and/or category tags for keywords you're interested in.
Let's say you have an array in your PHP script, i.e.
$keywords = array("php", "mysql", "open source");
Then, using SimpleXML you can parse the RSS feed:
function has_keywords($haystack, $wordlist)
{
$found = false;
foreach ($wordlist as $w)
{
if (stripos($haystack, $w) !== false) {
$found = true;
break;
}
}
return $found;
}
$rss = simplexml_load_file("http://www.mywebsite.com/my/rss/feed/");
foreach ($rss->channel->item as $i)
{
if (
has_keywords($i->title, $keywords)
|| has_keywords($i->description, $keywords)
|| has_keywords($i->category)
)
{
$news[] = array
(
"title" => $i->title,
"description" => $i->description,
"link" => $i->link
);
}
}
This will provide you with an array $news, populated with the data you've selected through the keyword check.
You can render this with any HTML code you want, by simply iterating through $news.
On a side note, you can also perform the same task with JavaScript and XMLHttpRequest, with no need of PHP intervention. Load the feed as an XML and go with the same procedure. To render the data, you can use document.createElement() to append the child nodes containing the information you've requested.

Categories