read xml with various namespaces with php - 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

Related

Insert XML result from curl to database

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;
}

Error is parsing the XML in PHP with simplexml

My XML to be parsed is in this format:
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header />
<env:Body>
<n0:ZFM_PAYSLIP1Response xmlns:n0="urn:sap-com:document:sap:rfc:functions">
<LS_EMP_PAYSLIP_DATA>
<ZEMP_NO>00199999</ZEMP_NO>
<ZEMP_NAME>AJ KUMAR</ZEMP_NAME>
<ZSAL_MONTH>JUL-2016</ZSAL_MONTH>
<ZBASIC_PAY>57240.0</ZBASIC_PAY>
<ZGROSS_PAY>145062.29</ZGROSS_PAY>
<ZNET_PAY>50728.0</ZNET_PAY>
<ZINCOME_TAX>25858.0</ZINCOME_TAX>
<ZLEAVE_ENCASH>0.0</ZLEAVE_ENCASH>
<ZDUTY_PAY>41976.0</ZDUTY_PAY>
<ZDA>56950.4</ZDA>
<ZPERKS>26330.4</ZPERKS>
<ZHRA>11448.0</ZHRA>
<ZTOT_DEDUCTIONS>94334.29</ZTOT_DEDUCTIONS>
<ZCPF>12787.0</ZCPF>
<ZVPF>50000.0</ZVPF>
<ZLIC>0.0</ZLIC>
<ZTHRIFT_FUND>0.0</ZTHRIFT_FUND>
<ZGRP_INS>160.0</ZGRP_INS>
<ZPROF_TAX>200.0</ZPROF_TAX>
<ZDUTY_DAYS>18</ZDUTY_DAYS>
<ZWEEK_OFF>4</ZWEEK_OFF>
<ZFL />
<ZCL />
<ZEL />
<ZFPL />
<ZHPL>8</ZHPL>
<ZCML />
<ZEOL />
<ZUAB />
<ZDEISGNATION>Sr.Manager(IT)</ZDEISGNATION>
<ZDEPT_CODE>03007900</ZDEPT_CODE>
<ZCL_BAL>3</ZCL_BAL>
<ZEL_BAL>270.5</ZEL_BAL>
<ZHPL_BAL>180</ZHPL_BAL>
</LS_EMP_PAYSLIP_DATA>
</n0:ZFM_PAYSLIP1Response>
</env:Body> </env:Envelope>
I am using PHP curl to get data from remote with
this PHP code :
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://hostanme.tld/ERP_PAY_XML.xml');
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
//echo $result;
curl_close($ch);
$xml = simplexml_load_string($result);
$ns = $xml->getNamespaces(true);
$soap = $xml->children($ns['env']);
echo "<br> len-soap : " . $soap;
$getaddressresponse = $soap->Body->children($ns['n0']);
foreach ($getaddressresponse->getLocationForGroupResponse->children($ns['n0']) as $item)
{
$item = $item->children();
echo $item->address . '<br />';
}
?>
but still I am not getting any result. Anybody please help..
Is there any other way to parse XML to an object..

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?

Parsing a XML response

I have been working on the Saia Carrier API and have it giving me values albeit they are not very appealing. I would like to parse the values and put them into variables so I can display them neatly in a table.
Here is the code:
<?php
$postdata = '<?xml version="1.0" encoding="utf-8"?>
<Create>
<UserID>XXX</UserID>
<Password>XXX</Password>
<TestMode>Y</TestMode>
<BillingTerms>Prepaid</BillingTerms>
<AccountNumber>XXX</AccountNumber>
<Application>Outbound</Application>
<OriginZipcode>44483</OriginZipcode>
<DestinationZipcode>90077</DestinationZipcode>
<Details>
<DetailItem>
<Weight>100</Weight>
<Class>85</Class>
</DetailItem>
</Details>
</Create>';
$url = "http://www.saiasecure.com/webservice/ratequote/xml.aspx";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS,$postdata);
curl_setopt($ch, CURLOPT_HTTPHEADER,array('Content-type: text/xml'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close ($ch);
$status = $info['http_code'];
echo $status;
echo '<pre>';
print_r($response);
?>
I got it.
Just added:
$xml = simplexml_load_string($response);
and changed:
print_r($response);
to:
print_r($xml);
I've always used PHP's SimpleXML library: http://php.net/manual/en/book.simplexml.php
This creates a pretty basic object that is easy to use and traverse.
This is an example of traversing with the children() function from the site: http://www.php.net/manual/en/simplexmlelement.children.php
<?php
$xml = new SimpleXMLElement(
'<person>
<child role="son">
<child role="daughter"/>
</child>
<child role="daughter">
<child role="son">
<child role="son"/>
</child>
</child>
</person>');
foreach ($xml->children() as $second_gen) {
echo ' The person begot a ' . $second_gen['role'];
foreach ($second_gen->children() as $third_gen) {
echo ' who begot a ' . $third_gen['role'] . ';';
foreach ($third_gen->children() as $fourth_gen) {
echo ' and that ' . $third_gen['role'] .
' begot a ' . $fourth_gen['role'];
}
}
}
?>
You can also retrieve attributes via the attributes() function: http://www.php.net/manual/en/simplexmlelement.attributes.php
<?php
$string = <<<XML
<a>
<foo name="one" game="lonely">1</foo>
</a>
XML;
$xml = simplexml_load_string($string);
foreach($xml->foo[0]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
?>

PHP and XML parsing

I'm struggling to parse an XML file in PHP:
Here's the XML
<rss xmlns:ac="http://palm.com/app.catalog.rss.extensions" version="2.0">
<channel>
<title>Device App Updates for US</title>
<link>http://www.palm.com</link>
<description>Updates</description>
<language>en-US</language>
<pubDate>Mon, 04 Jan 2010 18:23:51 -0800</pubDate>
<lastBuildDate>Mon, 04 Jan 2010 18:23:51 -0800</lastBuildDate>
<ac:distributionChannel>Device</ac:distributionChannel>
<ac:countryCode>US</ac:countryCode>
<item>
<title><![CDATA[My App]]></title>
<link>http://developer.palm.com/appredirect/?packageid=com.palm.myapp</link>
<description><![CDATA[My fun app.]]></description>
<pubDate>2009-12-21 21:00:58</pubDate>
<guid>334.232</guid>
<ac:total_downloads>1234</ac:total_downloads>
<ac:total_comments>12</ac:total_comments>
<ac:country>US</ac:country>
</item>
</channel>
</rss>
My Problem is; when I use:
$strURL = "http://developer.palm.com/rss/D/appcatalog.update.rss.xml";
$ch = curl_init($strURL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
$data = curl_exec($ch);
curl_close($ch);
$doc = new SimpleXmlElement($data, LIBXML_NOCDATA);
print_r($doc);
I'm not able to display the values? The one I'm most interested in is <ac:total_downloads>1000</ac> but I don't seem to be able to parse it.
What am I doing wrong?
Many thanks
You don't need to use curl to retrieve that file, SimpleXML can fetch external resources.
Use children() to access namespaced nodes. Here's how to do it:
$rss = simplexml_load_file($strURL);
$ns = 'http://palm.com/app.catalog.rss.extensions';
foreach ($rss->channel->item as $item)
{
echo 'Title: ', $item->title, "\n";
echo 'Downloads: ', $item->children($ns)->total_downloads, "\n\n";
}

Categories