Insert XML result from curl to database - php

I'm trying to insert the xml result from curl to database and I'm facing problems the data does not enter database. I have tried both mysqli method and PDO as well but the data does not enter database. Can anyone help me out with this.Here's my code:-
MYSQLI
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url."?".$queryString);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$parameters);
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
// Save response to the variable $data
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
// Close Curl connection
if ($data === False) {
echo "cURL ERROR:".curl_error($ch);
}
curl_close($ch);
echo $url."?".$queryString;
echo '<pre>';
echo htmlspecialchars(print_r($data, true));
echo '</pre>';
$xml= simplexml_load_string($data);
//print_r($xml) ;
con = mysqli_connect("localhost","root","");
mysqli_select_db($con,"test") or die(mysqli_connect_error());
foreach($xml -> Products as $product) {
$product->Product;
{
$name = mysqli_real_escape_string($product->name);
$short_description = mysqli_real_escape_string($product-
>short_description);
$brand = mysqli_real_escape_string($product->brand);
$model = mysqli_real_escape_string($product->model);
$warranty_type =mysqli_real_escape_string($product->warranty_type);
$sql = "Insert into test (name, short_description,
brand,model,warranty_type ) " . "Values
('$name','$short_description','$brand','$model','$warranty_type')";
$result = mysqli_query($con, $sql);
error_log($sql);
if (!$result) {
echo 'Error:' . mysqli_error($con);
} else {
echo 'Success';
}
}
}
**PDO**
$db= new PDO('mysql:host=localhost;dbname=test','root','');
$xmldoc= new DOMDocument();
$xmldoc -> load($data);
$xmldata = $xmldoc ->getElementsByTagName('Product');
$xmlcount = $xmldata ->length;
for($i=0; $i< $xmlcount; $i++){
$name = $xmldata -> item($i) ->getElementsByTagName('name')->item(0)->
childNodes->item(0)->nodeValue->item(0);
$short_description = $xmldata -> item($i) -
>getElementsByTagName('short_description')->item(0)-> childNodes->item(0)-
>nodeValue->item(0);
$brand = $xmldata -> item($i) ->getElementsByTagName('brand')->item(0)->
childNodes->item(0)->nodeValue->item(0);
$model = $xmldata -> item($i) ->getElementsByTagName('model')->item(0)->
childNodes->item(0)->nodeValue->item(0);
$warranty_type = $xmldata -> item($i) -
>getElementsByTagName('warranty_type')->item(0)-> childNodes->item(0)-
>nodeValue->item(0);
$stmt = $db->prepare("insert into test values(?,?,?,?,?)");
$stmt -> bindParam(1,$name);
$stmt -> bindParam(2,$short_description);
$stmt -> bindParam(3,$brand);
$stmt -> bindParam(4,$model);
$stmt -> bindParam(5,$warranty_type);
$stmt ->execute();
}
The PDO method shows that getElementsByTagName not found in DOMNode. I am using PHPStorm 2016.2.1 as my IDE.
This is the response I get from curl in xml format
<SuccessResponse>
<Head>
<RequestId>0a1530d415089888818591159e</RequestId>
<RequestAction>GetProducts</RequestAction>
<ResponseType>Product</ResponseType>
<Timestamp>2017-10-26T03:34:40+0000</Timestamp>
<isES>true</isES>
</Head>
<Body>
<TotalProducts>589</TotalProducts>
<Products>
<Product>
<PrimaryCategory>10001164</PrimaryCategory>
<SPUId/>
<Attributes>
<name>Big Rabbit Furry Key Chain (Light Blue)</name>
<short_description><ul> <li><span style="font-
family:arial,sans-serif; font-size:10pt">A perfect gift for yourself
or someone special</span></li> <li><span style="font-
family:arial,sans-serif; font-size:10pt">Good accessory for handbag,
tote backpack cellphones, keychain or car</span></li>
<li><span style="color:rgb(17, 17, 17); font-family:arial,sans-
serif; font-size:10pt">Super cute and soft</span></li>
<li><span style="color:rgb(17, 17, 17); font-family:arial,sans-
serif; font-size:10pt">Ideal companion of your keys, bags, cellphones
car or other wonderful objects</span></li> <li><span
style="color:black; font-family:arial,sans-serif; font-
size:10pt">Size(cm): 10 x 6 x 18</span></li> </ul>
</short_description>
<video/>
<services/>
<brand>Not Specified</brand>
<model>bulu15-lightblue</model>
<color_family/>
<Hazmat/>
<warranty_type>No Warranty</warranty_type>
<warranty/>
<product_warranty/>
<name_ms>Big Rabbit Furry Key Chain (Light Blue)</name_ms>
<product_warranty_en/>
<description_ms/>
<external_url/>
</Attributes>
<Skus>
<Sku>
<Status>active</Status>
<quantity>100</quantity>
<tax_class>default</tax_class>
<_compatible_variation_>...</_compatible_variation_>
<SellerSku>test112</SellerSku>
<ShopSku/>
<package_content><p>1 x Big Rabbit Furry Key Chain (Light Blue)</p></package_content>
<Url/>
<package_width>6.00</package_width>
<package_height>18.00</package_height>
<special_price>0.0</special_price>
<price>0.0</price>
<package_length>10.00</package_length>
<package_weight>0.10</package_weight>
<Available>100</Available>
<Images>
<Image>https://my-live.slatic.net/original/601531319cd1dca721c70637e96cc403.jpg</Image>
<Image>https://my-live.slatic.net/original/7e6ad47bbfa1de474fe36c20b06c35f7.jpg</Image>
<Image>https://my-live.slatic.net/original/02bc2102d6864a867c25328724f0c7c7.jpg</Image>
<Image/>
<Image/>
<Image/>
<Image/>
<Image/>
</Images>
</Sku>
</Skus>
</Product>

There are a few issues with your PDO version of the code.
The first is that your using $xmldoc -> load($data);, load() is expecting a file name and your passing in the actual data. So change this to loadXML().
Then when your accessing the elements of the data, your using
->nodeValue->item(0). nodeValue gives you the contents of the node, so you need to stop at this point. In the code below, I've just changed it for the name, but you should see how this needs to be changed through your code.
$xmldoc= new DOMDocument();
$xmldoc -> loadXML($data);
$xmldata = $xmldoc ->getElementsByTagName('Product');
$xmlcount = $xmldata ->length;
for($i=0; $i< $xmlcount; $i++){
$name = $xmldata -> item($i) ->getElementsByTagName('name')->item(0)->
childNodes->item(0)->nodeValue;
echo $name;
}

Related

DOM parsing with php is returning zero child elements

I want to extract url data just like as facebook. For that I am using php DOMDocument.While retrieving the DOM content i.e while retrieving "title" the DOMDocument is returning 0 elements. Here is my code
<?php
header("Content-Type: text/xml");
echo '<?xml version="1.0" encoding="UTF-8" ?>';
//$url = $_REQUEST["url"];
$url = "http://business.tutsplus.com/articles/how-to-set-up-your-first-magento-store--fsw-43137";
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
$data = curl_exec($ch);
curl_close($ch);
$dom = new DOMDocument();
#$dom->loadHTML($data);
$title = $dom->getElementsByTagName("title");
//$title = $dom->find("title");
echo "<urlData>";
echo "<title>";
echo $title->length;
echo "</title>";
echo "</urlData>";
?>
Here $title->length is returning 0 elements. What is the problem?

XML cleaning [xml:space] using PHP

How to remove all nodes like xml:space="preserve" from XML, to get clean result
old XML
<table>
<actor xml:space="preserve"> </actor>
</table>
I want result be like this
<table>
<actor> </actor>
</table>
EDIT
this the php code
function produce_XML_object_tree($raw_XML) {
libxml_use_internal_errors(true);
try {
$xmlTree = new SimpleXMLElement($raw_XML);
} catch (Exception $e) {
// Something went wrong.
$error_message = 'SimpleXMLElement threw an exception.';
foreach(libxml_get_errors() as $error_line) {
$error_message .= "\t" . $error_line->message;
}
trigger_error($error_message);
return false;
}
return $xmlTree;
}
$xml_feed_url = "www.xmlpage.com/web.xml";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $xml_feed_url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$xml = curl_exec($ch);
curl_close($ch);
$cont = produce_XML_object_tree($xml);
echo json_encode($cont);
Use an xpath expression to locate the attributes and remove them.
Example:
//$xml = your xml string
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
foreach ($xpath->query('//#xml:space') as $attr) {
$attr->ownerElement->removeAttributeNode($attr);
}
echo $dom->saveXML();
Output:
<?xml version="1.0"?>
<table>
<actor> </actor>
</table>
This will remove any xml:space attributes. If you want to target only those xml:space attributes that have a value of "preserve", change the query to //#xml:space[.="preserve"].
$string = str_ireplace('xml:space="preserve"','',$string);
function produce_XML_object_tree($raw_XML) {
libxml_use_internal_errors(true);
try {
$xmlTree = new SimpleXMLElement($raw_XML);
} catch (Exception $e) {
// Something went wrong.
$error_message = 'SimpleXMLElement threw an exception.';
foreach(libxml_get_errors() as $error_line) {
$error_message .= "\t" . $error_line->message;
}
trigger_error($error_message);
return false;
}
return str_ireplace('xml:space="preserve"','',$xmlTree;);
}
$xml_feed_url = "www.xmlpage.com/web.xml";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $xml_feed_url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$xml = curl_exec($ch);
curl_close($ch);
$cont = produce_XML_object_tree($xml);
echo json_encode($cont);
As long as you're concerned to remove all attribute-nodes that are with a namespace prefix, you can do so by selecting them via xpath and remove them from the XML document.
The xpath query for all attributes with a prefix can be obtained by comparing the name (that is prefix and local-name) with the local-name (that is the local-name only). If it differs you've got a match:
//#*[name(.) != local-name(.)]
Querying specific nodes with SimpleXML and XPath to delete them has been outlined earlier as an answer to the question Remove a child with a specific attribute, in SimpleXML for PHP (Nov 2008) and is pretty straight-forward by using the SimpleXML-Self-Reference:
$xml = simplexml_load_string($buffer);
foreach ($xml->xpath('//#*[name(.) != local-name(.)]') as $attr) {
unset($attr[0]);
}
The self-reference here is to remove the attribute $attr via $attr[0].
Full Example:
$buffer = <<<XML
<table>
<actor class="foo" xml:space="preserve"> </actor>
</table>
XML;
$xml = simplexml_load_string($buffer);
foreach ($xml->xpath('//#*[name(.) != local-name(.)]') as $attr) {
unset($attr[0]);
}
echo $xml->asXML();
Example Output:
<?xml version="1.0"?>
<table>
<actor class="foo"> </actor>
</table>

php process xml into array

I'm tring to process xml (website) into php array.
I have tried the following code which works for everyting in results but i need to get the totalpage which i'm not able to see how I can do this.
function get_content($url)
/// basically opens the page and stores it as a variable. Buggered if I know how it works!
{
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_HEADER, 0);
ob_start();
curl_exec ($ch);
curl_close ($ch);
$string = ob_get_contents();
ob_end_clean();
return $string;
$string = NULL;
$ch = NULL;
$url = NULL;
}
$url = "url";
$content = get_content($url);
$content_x = explode("<result>", $content);
foreach ($content_x as $item)
{
$p1 = strpos($item, '<title>');
$p2 = strpos($item, '</title>');
$l1 = $p2 - $p1;
echo '<br>'.$title = substr($item, $p1, $l1);
}
xml site feed
<?xml version="1.0" encoding="UTF-8"?>
<response version="2">
<totalpage>1005</totalpage>
<results>
<result>
<title>test</title>
<title2>test2</title2>
<title3>test3</title3>
<result>
<result>
<title>test</title>
<title2>test2</title2>
<title3>test3</title3>
<result>
<result>
<title>test</title>
<title2>test2</title2>
<title3>test3</title3>
<result>
........so on
<results>
</response>
I need to get totalpage and everyting in results
How do get totalpage and is they better way to process the results
You absolutely should not be using string manipulation to try to parse XML. There are any number of PHP libraries that can do this. I might recommend SimpleXML.
Usage would be:
$xml = simplexml_load_string($content);
$totalpage = $xml->response->totalpage;

read xml with various namespaces with php

I have to parse an xml file that contains various namespaces.
I have already registered the namespaces.
My problem is that I cannot extract the data from the cal:location block.
For example i need the vcard:street-address or the vcard:postal-code.
XML - Example:
<channel>
<title>Veranstaltungen zum Thema Markt+Bauer vom 05.05.2011 bis 05.05.2012</title>
<link>https://www.wien.gv.at/vadb/internet/AdvPrSrv.asp?Layout=VAErgebnis_neu&Type=S&ganzjaehrig=ja</link>
<description> Veranstaltungen zum Thema Markt+Bauer vom 05.05.2011 bis 05.05.2012 </description>
<lastBuildDate>Sa,05 Jän 2013 17:38:05 GMT</lastBuildDate>
<ManagingEditor>event#ma55.wien.gv.at</ManagingEditor>
<language>de-AT</language>
<dc:license>http://data.wien.gv.at/nutzungsbedingungen</dc:license>
<dc:rightsHolder>Stadt Wien</dc:rightsHolder>
<item>
<title>Bauernmarkt am Karmelitermarkt</title>
<link>https://www.wien.gv.at/vadb/internet/AdvPrSrv.asp?Layout=VAErgebnis_neu&Type=K&ID=256811&return=</link>
<guid isPermaLink="false">https://www.wien.gv.at/vadb/internet/AdvPrSrv.asp?Layout=VAErgebnis_neu&Type=K&ID=256811&return=</guid>
<description><![CDATA[
<p>07.01.2011 bis 31.12.2011<br />
08:00 bis 13:00<br />
Karmelitermarkt<br />http://www.wiener-maerkte.at</p>­<p>Spezieller Bauernmarkt mit köstlichen naturreinen Produkten.</p>]]>
</description>
<category>Kulinarischer Markt</category>
<dc:subject>Kulinarischer Markt</dc:subject>
<cal:dtstart>2011-01-07T00:00:00+01:00</cal:dtstart>
<cal:dtend>2011-12-31T00:00:00+01:00</cal:dtend>
<cal:byday>Fr, Sa</cal:byday>
<cal:byhour>08</cal:byhour>
<cal:byminute>00</cal:byminute>
<cal:location>
<vcard:fn>Karmelitermarkt</vcard:fn>
<vcard:street-address>Haidgasse 1</vcard:street-address>
<vcard:postal-code>1020</vcard:postal-code>
<vcard:tel/>
<vcard:fax/>
<vcard:email>office#wiener-maerkte.at</vcard:email>
<vcard:url>http://www.wiener-maerkte.at</vcard:url>
</cal:location>
<cal:organizer>
<vcard:fn>Wiener Einkaufsstraßen-Management</vcard:fn>
<vcard:street-address>Hietzinger Kai 133</vcard:street-address>
<vcard:postal-code>1130</vcard:postal-code>
<vcard:tel>0043-1/514 50-6700</vcard:tel>
<vcard:fax>0043-1/514 50-6749</vcard:fax>
<vcard:email/>
<vcard:url>http://www.einkaufsstrassen.at</vcard:url>
</cal:organizer>
</item>
</channel>
My PHP - Code:
<?php
function download_feed($path){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$path);
curl_setopt($ch, CURLOPT_FAILONERROR,1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,15);
$retValue = curl_exec($ch);
curl_close($ch);
return $retValue;
}
$sXML = download_feed('xml - Example');
$oXML = new SimpleXMLElement($sXML);
foreach($oXML->channel->item as $oDocument){
$title = $oDocument->title;
$url = $oDocument->link;
$namespaces = $oDocument->getNameSpaces(true);
$cal = $oDocument->children($namespaces['cal']);
$vcard = $cal->children($namespaces['vcard']);
$dc = $oDocument->children($namespaces['dc']);
$georss = $oDocument->children($namespaces['georss']);
$byday = $cal->byday;
//var_dump($vcard);
$attrs = $oDocument->getElementsByTagName("vcard:fn");
$streetAddress = $oDocument->{'cal:location'}->{'vcard:fn'};
echo $title . "<br>" . $url . "<br>" . $byday. "<br>" . $streetAddress. "<br><br>";
}
?>
You've misunderstood the purpose of the ->children() method: it doesn't "register" namespaces, it selects them for immediate use.
So to get to <cal:location>, you can use $oDocument->children($namespaces['cal'])->location, and the <vcard:fn> inside that would be $oDocument->children($namespaces['cal'])->location->children($namespaces['vcard'])->fn
Since PHP 5.2, you can also use prefixes directly, rather than looking up their URLs, by giving the ->children() method an extra parameter of true: $oDocument->children('cal', true)->location->children('vcard', true)->fn

Selecting a content type from youtube API

I have an xml feed from the youtube API. So far I have successfully lifted the title,thumbnail, ratings etc. However I am struggling to parse the content url from the following feed.
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/'>
<entry>
<media:group>
<media:content url='http://www.youtube.com/v/ZTUVgYoeN_b?f=gdata_standard...' type='application/x-shockwave-flash' medium='video' isDefault='true' expression='full' duration='215' yt:format='5'/>
<media:content url='rtsp://rtsp2.youtube.com/ChoLENy73bIAEQ1kgGDA==/0/0/0/video.3gp' type='video/3gpp' medium='video' expression='full' duration='215' yt:format='1'/>
<media:content url='rtsp://rtsp2.youtube.com/ChoLENy73bIDRQ1kgGDA==/0/0/0/video.3gp' type='video/3gpp' medium='video' expression='full' duration='215' yt:format='6'/>
</media:group>
</entry>
</feed>
Below is my code so far. I believe this has worked for other items because I was not selecting from multiple nodes i.e. there is only one title, thumbnail url etc...
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $xml_feed_url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$xml = curl_exec($ch);
curl_close($ch);
$feed = produce_XML_object_tree($xml);
$entry = $feed->entry;
$media = $entry->children('http://search.yahoo.com/mrss/');
$urla=$media->content->attributes();
$url=$urla["url"];
function produce_XML_object_tree($raw_XML)
{
libxml_use_internal_errors(true);
try
{
$xmlTree = new SimpleXMLElement($raw_XML);
}
catch (Exception $e)
{
// Something went wrong.
$error_message = 'SimpleXMLElement threw an exception.';
foreach(libxml_get_errors() as $error_line)
{
$error_message .= "\t" . $error_line->message;
}
trigger_error($error_message);
return false;
}
return $xmlTree;
}
How can I select one of these content types?
Solved
To select one of the content types I just had to use a simple index. Hopefully this is a lesson I only need to learn once:
$urla=$media->group->content[0]->attributes();
$url=$urla["url"];

Categories