Read XML dynamic PHP - php

in my site in PHP I want to read an xml file like this:
<?xml version="1.0" standalone="yes"?>
<RETURNDATA lang="it-IT" type="COR" xsi:noNamespaceSchemaLocation="http://xmlv5test.travco.co.uk/trlink/schema/CountryRequestV6Rcv.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MESSAGE>All Countries details and relevant city details</MESSAGE>
<DATA COUNTRY_CODE="ABW" CURRENCY_CODE="EUR">
<COUNTRY_NAME>Aruba</COUNTRY_NAME>
<CURRENCY_NAME>euro</CURRENCY_NAME>
<COUNTRY_CITIES>
<CITY_DATA CITY_CODE="AUA">
<CITY_NAME>Aruba</CITY_NAME>
</CITY_DATA>
</COUNTRY_CITIES>
</DATA>
<DATA COUNTRY_CODE="ALB" CURRENCY_CODE="EUR">
<COUNTRY_NAME>Albania</COUNTRY_NAME>
<CURRENCY_NAME>euro</CURRENCY_NAME>
<COUNTRY_CITIES>
<CITY_DATA CITY_CODE="TIA">
<CITY_NAME>Tirana</CITY_NAME>
</CITY_DATA>
</COUNTRY_CITIES>
</DATA>
<DATA COUNTRY_CODE="ARE" CURRENCY_CODE="EUR">
<COUNTRY_NAME>Emirati Arabi Uniti</COUNTRY_NAME>
<CURRENCY_NAME>euro</CURRENCY_NAME>
<COUNTRY_CITIES>
<CITY_DATA CITY_CODE="DXB">
<CITY_NAME>Dubai</CITY_NAME>
</CITY_DATA>
<CITY_DATA CITY_CODE="AAI">
<CITY_NAME>Al Ain</CITY_NAME>
</CITY_DATA>
<CITY_DATA CITY_CODE="FJR">
<CITY_NAME>Fujaira</CITY_NAME>
</CITY_DATA>
<CITY_DATA CITY_CODE="SSH">
<CITY_NAME>Sharja</CITY_NAME>
</CITY_DATA>
<CITY_DATA CITY_CODE="RKT">
<CITY_NAME>Ras al-Khaimah</CITY_NAME>
</CITY_DATA>
<CITY_DATA CITY_CODE="AUH">
<CITY_NAME>Abu Dhabi</CITY_NAME>
</CITY_DATA>
</COUNTRY_CITIES>
</DATA>
</RETURNDATA>
I want to enter in each node name DATA and take:
COUNTRY_CODE
CURRENCY_CODE
COUNTRY_NAME
CURRENCY_NAME
And all ountry cities code and name into an array associative.
I have tried with SimpleXML, but the XML is dynamic and I wanto to optimize my cycle because I can have a very big and large XML (this is only a little part of It).
$xml_str = file_get_contents('xml/country.xml');
$xml = new SimpleXMLElement($xml_str);
echo $xml->getName(), PHP_EOL;
foreach($xml as $name => $part) {
echo "$name: $part", PHP_EOL;
}
I want to create a very otpimize cycle to take my value

Use the following style to acces only the <DATA> child elements in the root element:
foreach ($xml->DATA as $name => $part) {
Also please check the SimpleXML Introduction it should have some good examples for you showing different ways how to do the basic stuff with SimpleXML. The documentation is pretty good.

you could use the XML parser directly, this would more than likely be the most efficient way
set_time_limit(0);
define('__BUFFER_SIZE__', 131072);
define('__XML_FILE__', 'pf_1360591.xml');
function elementStart($p, $n, $a) {
//handle opening of elements
}
function elementEnd($p, $n) {
//handle closing of elements
}
function elementData($p, $d) {
//handle cdata in elements
}
$xml = xml_parser_create();
xml_parser_set_option($xml, XML_OPTION_TARGET_ENCODING, 'UTF-8');
xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
xml_set_element_handler($xml, 'elementStart', 'elementEnd');
xml_set_character_data_handler($xml, 'elementData');
$f = fopen(__XML_FILE__, 'r');
if($f) {
while(!feof($f)) {
$content = fread($f, __BUFFER_SIZE__);
xml_parse($xml, $content, feof($f));
unset($content);
}
fclose($f);
}

Related

SimpleXML foreach doesn't work

I have following XML (source.xml):
<SHOP>
<SHOPITEM>
<ITEM_ID>3664</ITEM_ID>
<PRODUCT>Product n.1</PRODUCT>
<PRODUCT_NAME>Product n.1</PRODUCT_NAME>
<VARIANT_NAME/>
<MANUFACTURER>Jeffrey</MANUFACTURER>
<CODE>ABC123</CODE>
<EAN>123456789</EAN>
<DESCRIPTION>
Maybe later...
</DESCRIPTION>
<DESCRIPTION_HTML/>
<CATEGORIES>
<CATEGORY id="1" parent_id="0">ABx</CATEGORY>
</CATEGORIES>
</SHOPITEM>
<SHOPITEM>
...etc
And following code:
$xml = simplexml_load_file("source.xml", NULL, LIBXML_NOCDATA);
foreach ($xml->shopitem as $shopitem) {
echo $shopitem->item_id;
}
Unfortunately, it doesn't work. Even if I put echo 'a'; into foreach cycle, nothing appears. XML is valid. Tried var_dump($xml) and the XML looks to be loaded correctly. What is wrong? Thank you.
$xml = simplexml_load_file("source.xml", NULL, LIBXML_NOCDATA);
foreach ($xml->SHOPITEM as $shopitem) {
echo $shopitem->ITEM_ID;
}

simplexml_load_string cannot load XML / No error / result not === false

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<result sync="false" version="2">
<action>start-subscription</action>
<action_result>
<code>103</code>
<detail>1 missing parameter</detail>
<missing_parameters>
<missing_parameter>
<key>operator</key>
</missing_parameter>
</missing_parameters>
<status>1</status>
</action_result>
<custom_parameters>
<custom_parameter>
<key>cp_REF</key>
<value>simpleLPADULTCHSMSV2___WoopGang------___Adjomo___external___paid___android___CH___WIFI___locale=fr_FR</value>
</custom_parameter>
</custom_parameters>
<customer>
<country>CH</country>
<language>en</language>
</customer>
<payment_parameters>
<channel>web</channel>
<method>OPERATOR</method>
<order>90330</order>
</payment_parameters>
<transactions>
<transaction>
<id>1308636894</id>
<status>-1</status>
</transaction>
</transactions>
<request_id>1591621_t593818e0f3913</request_id>
<reference>09045c8e-9ec1-4306-8699-5ac5306983b2</reference>
</result>
PHP:
$xml = file_get_contents("php://input");
$datas = array();
parse_str($xml, $datas);
$data = $datas['data'];
libxml_use_internal_errors(true);
$xml = simplexml_load_string($data);
if($xml === false){
foreach(libxml_get_errors() as $error) {
$this->_logCall(self::LOG_DIMOCO, $error->message,"--");
}
}else{
$this->_logCall(self::LOG_DIMOCO, 'loaded simpleXML '.print_r($xml), ' --');
}
Running that ends in the last ELSE and the result is "1"
Any idea what I'm doing wrong ?
I have to add some text because apparently its mostly code and not understandable. Now ? Now ? Now ? Now ?
print_r() (by default) doesn't return output, it prints it -- so you can't use it in a string context. If you want to do that, you can pass a truthy value as the second parameter to have it return the output instead of printing it:
$this->_logCall(self::LOG_DIMOCO, 'loaded simpleXML '.print_r($xml, true), ' --');

extracting a log file which has xml in it

I have a log file whose content is like the one below
2016-04-07 19:37:48 <order merchant="asc" affiliate="" id="UM9E-C01101518" date="1443723720" event_id="1" ref="GDVJT" alias="asc">
<event type="sale" date="2015-10-01 18:22:00" status_code="SA">
<sale amount="61.45" amount_usd="43.94" method="VISA" currency="CAD" processor="visa"/>
<tax amount="7.37" amount_usd="5.28" currency="CAD"/>
<payout amount="39.89" currency="USD"/>
</event>
<customer>
<name>Frank</name>
<email>frank#gmail.com</email>
<address/>
<region>BC</region>
<country>IN</country>
<zip_postal>V8V1J9</zip_postal>
<phone_number>1231231234</phone_number>
<language>EN</language>
<ip>209.13.233.227</ip>
<currency>CAD</currency>
</customer>
I am trying to extract the value of name and email from this log file.
I am using the below code:
$handle = fopen('vendorOrder.log','r') or die ('File opening failed');
while (!feof($handle)) {
$dd = fgets($handle);
$str = htmlentities($dd, ENT_XHTML);
if(preg_match("/<name>(.*)<\/name>/",$str)){
$txt = getTextBetweenTags($str, "name");
echo $txt;
}
}
fclose($handle);
function getTextBetweenTags($string, $tagname) {
$pattern = "/<$tagname>(.*)<\/$tagname>/";
preg_match($pattern, $string, $matches);
return $matches[0];
}
But it is never matching the name tag and I am not able to get the value between the tags.
I need the output as Frank.
Can someone let me know whats wrong in the code
Use simplexml_load_file() php function.
Example:
$xml=simplexml_load_file("vendorOrder.log") or die("Error: Cannot create object");
And get this value with $xml->customer->name
Maybe your XML are crashed. Try this format.
<order merchant="asc" affiliate="" id="UM9E-C01101518" date="1443723720" event_id="1" ref="GDVJT" alias="asc">
<event type="sale" date="2015-10-01 18:22:00" status_code="SA">
<sale amount="61.45" amount_usd="43.94" method="VISA" currency="CAD" processor="visa"/>
<tax amount="7.37" amount_usd="5.28" currency="CAD"/>
<payout amount="39.89" currency="USD"/>
</event>
<customer>
<datetime>2016-04-07 19:37:48</datetime>
<name>Frank</name>
<email>frank#gmail.com</email>
<address/>
<region>BC</region>
<country>IN</country>
<zip_postal>V8V1J9</zip_postal>
<phone_number>1231231234</phone_number>
<language>EN</language>
<ip>209.13.233.227</ip>
<currency>CAD</currency>
</customer>
</order>
Yup as stated use simplexml_load_file($url) ; to parse xml.
you can find examples here : http://www.w3schools.com/php/php_xml_simplexml_get.asp
Make a correction in original string with something like this:
<?php
$xml_file = 'vendorOrder.log';
$xml_content = file_get_contents( $xml_file );
$xml_content .= "\n</order>";
$xml_content = substr( $xml_content, 20 );
var_dump($xml_content);
$xml=simplexml_load_string($xml_content) or die("Error: Cannot create object");
echo $xml->customer->name;

Reading XML with PHP. Not work (namespaces)

I can read XML files or strings but not the next:
$str = <<<XML
<Output xmlns="nice.uniform://" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Data i:nil="true"/>
<Result xmlns:a="http://nice.uniform/CLSAPI3">
<a:ResultCode>SUCCESS</a:ResultCode>
<a:ResultMessage>OK</a:ResultMessage>
<a:ResultCodeEx>CLS_SE_SUCCESS</a:ResultCodeEx>
</Result>
<Exception i:nil="true" xmlns:a="http://schemas.datacontract.org/2004/07/System"/>
</Output>
XML;
My PHP code to read a node of XML file is:
$Output = new SimpleXMLElement($str);
echo $Output->Result->{'a:ResultCodeEx'};
Also, I've tried:
$xmlResponse = simplexml_load_file('file.xml');
foreach($xmlResponse->Result as $xmlEntry)
{
echo $xmlEntry->{'a:ResultCodeEx'};
}
//or
$blocks = $xmlResponse->xpath('//Output');
print_r($blocks);
Can you help me?
The document uses several namespaces. The element ResultCodeEx belongs to the namespace a. You can use XPath, but you need to register the namespace a before the query:
$Output = new SimpleXMLElement($str);
$Output->registerXPathNamespace ('a', 'http://nice.uniform/CLSAPI3');
$result = $Output->xpath('//a:ResultCodeEx/text()');
echo $result[0]; // CLS_SE_SUCCESS

Reading XML with PHP

I am testing out some things with reading XML using PHP. The below is a sample of the XML File:
<?xml version="1.0" encoding="UTF-8" ?>
<BroadcastData creationDate="20140326085217">
<ScheduleData>
<ChannelPeriod beginTime="20140326090000" endTime="20140402044500">
<ChannelId>Rai Uno</ChannelId>
<Event beginTime="20140326090000" duration="1800">
<EventId>260852180006</EventId>
<EventType>P</EventType>
<EpgProduction>
<EpgText language="eng">
<Name>Unomattina storie vere</Name>
</EpgText>
</EpgProduction>
</Event>
<Event beginTime="20140326093000" duration="1500">
<EventId>260852180007</EventId>
<EventType>P</EventType>
<EpgProduction>
<EpgText language="eng">
<Name>Unomattina Verde</Name>
</EpgText>
</EpgProduction>
</Event>
This is the PHP Script I built, however notthing is showing on when I run the PHP file.
<?php
$completeurl ="test.xml";
$xml = simplexml_load_file($completeurl);
$info = $xml->BroadcastData->ScheduleData->ChannelPeriod->ChannelId;
for ($i = 0; $i++) {
$begintime = $info[$i]->Event->attributes()->beginTime;
echo "<p>Channel: ".$info."<br/>"."Begin Time: ".$begintime."</p>";
}
?>
Many thanks for your help guys !
You should iterate over each channel period rather than channel id (which is a sub element anyway):
$doc = simplexml_load_file($completeurl);
foreach ($doc->ScheduleData->ChannelPeriod as $channelPeriod) {
$channelId = (string)$channelPeriod->ChannelId;
foreach ($channelPeriod->Event as $event) {
$beginTime = $event['beginTime'];
printf('<p>Channel: %s<br />Begin Time: %s</p>', $channelId, $beginTime);
}
}
use following function to convert the xml string into array
json_decode(json_encode((array)simplexml_load_string($sXML)),1);

Categories