Repurposing data from simpleXML to an array - php

I'm having trouble accessing variable from an object. The object is coming from an API feed and a var_dump looks like this:
object(stdClass)#2 (1) {
["GetBookingsResult"]=>
string(189227) "<Bookings>
<Data>
<BookingDate>2012-01-06T00:00:00-06:00</BookingDate>
<StartBookingDate>2012-01-06T00:00:00-06:00</StartBookingDate>
<RoomDescription>Dorm A</RoomDescription>
<TimeEventStart>2012-01-06T15:00:00-06:00</TimeEventStart>
<TimeEventEnd>2012-01-07T00:00:00-06:00</TimeEventEnd>
<GroupName>Family Retreat</GroupName>
<EventName>Family Retreat</EventName>
<SetupTypeDescription>(none)</SetupTypeDescription>
<SetupCount>27</SetupCount>
<ReservationID>1222</ReservationID>
<EventCoordinator />
<GroupID>12</GroupID>
<VIP xml:space="preserve"> </VIP>
<VIPEvent>false</VIPEvent>
<ClosedAllDay>false</ClosedAllDay>
<OpenTime>1900-01-01T00:00:00-06:00</OpenTime>
<CloseTime>1900-01-01T00:00:00-06:00</CloseTime>
<GroupTypeDescription>Religious - Conference</GroupTypeDescription>
<EventTypeDescription>Retreat</EventTypeDescription>
<Contact>Phyllis 0000000000</Contact>
<AltContact />
<BookingID>29512</BookingID>
<TimeBookingStart>2012-01-06T15:00:00-06:00</TimeBookingStart>
<TimeBookingEnd>2012-01-07T00:00:00-06:00</TimeBookingEnd>
<GMTStartTime>2012-01-06T15:00:00-06:00</GMTStartTime>
<GMTEndTime>2012-01-07T00:00:00-06:00</GMTEndTime>
<BuildingCode>Asb</BuildingCode>
<Building>Dormitory</Building>
<RoomCode>ASB A</RoomCode>
<Room>Dorm A</Room>
<RoomID>181</RoomID>
<BuildingID>20</BuildingID>
<StatusID>1</StatusID>
<StatusTypeID>-14</StatusTypeID>
<EventTypeID>1</EventTypeID>
<GroupTypeID>1</GroupTypeID>
<DateAdded>2011-01-09T08:25:02.72-06:00</DateAdded>
<AddedBy>B Jordan</AddedBy>
<DateChanged>2012-01-08T08:34:23.2-06:00</DateChanged>
<ChangedBy>J Smith</ChangedBy>
</Data>
<Data>
<BookingDate>2012-01-06T00:00:00-06:00</BookingDate>
<StartBookingDate>2012-01-06T00:00:00-06:00</StartBookingDate>
<RoomDescription>Dorm A1</RoomDescription>
<TimeEventStart>2012-01-06T15:00:00-06:00</TimeEventStart>
<TimeEventEnd>2012-01-07T00:00:00-06:00</TimeEventEnd>
<GroupName>Family Retreat</GroupName>
<EventName>Family Retreat</EventName>
<SetupTypeDescription>(none)</SetupTypeDescription>
<SetupCount>27</SetupCount>
<ReservationID>1222</ReservationID>
<EventCoordinator />
<GroupID>12</GroupID>
<VIP xml:space="preserve"> </VIP>
<VIPEvent>false</VIPEvent>
<ClosedAllDay>false</ClosedAllDay>
<OpenTime>1900-01-01T00:00:00-06:00</OpenTime>
<CloseTime>1900-01-01T00:00:00-06:00</CloseTime>
<GroupTypeDescription>Religious - Conference</GroupTypeDescription>
<EventTypeDescription>Retreat</EventTypeDescription>
<Contact>Phyllis 0000000000</Contact>
<AltContact />
<BookingID>29512</BookingID>
<TimeBookingStart>2012-01-06T15:00:00-06:00</TimeBookingStart>
<TimeBookingEnd>2012-01-07T00:00:00-06:00</TimeBookingEnd>
<GMTStartTime>2012-01-06T15:00:00-06:00</GMTStartTime>
<GMTEndTime>2012-01-07T00:00:00-06:00</GMTEndTime>
<BuildingCode>Asb</BuildingCode>
<Building>Dormitory</Building>
<RoomCode>Asb A1</RoomCode>
<Room>Dorm A1</Room>
<RoomID>7</RoomID>
<BuildingID>20</BuildingID>
<StatusID>1</StatusID>
<StatusTypeID>-14</StatusTypeID>
<EventTypeID>1</EventTypeID>
<GroupTypeID>1</GroupTypeID>
<DateAdded>2011-01-09T08:25:02.72-06:00</DateAdded>
<AddedBy>P Jordan</AddedBy>
<DateChanged>2012-01-08T08:34:23.2-06:00</DateChanged>
<ChangedBy>J Smith</ChangedBy>
</Data>
</Bookings>"
}
I want to be able to reorder the info that comes back into an array so that I can group the events by date and then order them by EventName. Below is my code:
$xml = simplexml_load_string($result->GetBookingsResult);
$list='';
foreach($xml as $event){
$st_date = lvmDateFormat($event->TimeBookingStart,'name');//function reformats date
$en_date = lvmDateFormat($event->TimeBookingEnd,'name');
$name = lvmDateFormat($event->TimeBookingStart,'cal');
$ename = $event->EventName;
$events[lvmDateFormat($event->TimeBookingStart,'name')][$st_date] = array(
'EventName' => $ename
,'Date' => $name
,'TimeEventStart' => $st_date
,'TimeEventEnd' => $en_date
);
}
If I echo out $event->EventName; it looks fine, but when I try to add it to an array it comes back like this:
[EventName] => SimpleXMLElement Object
(
[0] => UMW Training Event
)
What am I doing wrong here?
Ta

When you echo an object, it is converted to a string. So it will appear (because SimpleXMLElement defines a __toString() method internally) like you want it to - but the type of the $event variable is still an object of type SimpleXMLElement.
You can easily store it as a string in the array, if you cast it to a string. Try changing this line:
$ename = $event->EventName;
...to this:
$ename = (string) $event->EventName;

Related

How to load xml data with namespace

So the XML I am trying to load looks something like this:
<tns:PersonListOutput xmlns:tns="http://www.example.com/api/person">
<tns:LastName>Doe</tns:LastName>
<tns:TransmissionDate>2018-03-02T10:16:23</tns:TransmissionDate>
<tns:People>
<tns:Person>
<tns:Name>John Doe</tns:Name>
<tns:RevisionDate>2017-08-10T01:45:40</tns:RevisionDate>
</tns:Person>
<tns:Person>
<tns:Name>Jane Doe</tns:Name>
<tns:RevisionDate>2017-08-10T01:45:43</tns:RevisionDate>
</tns:Person>
</tns:People>
</tns:PersonListOutput>
I am loading this data from a URL using the following code:
$response_xml_data = file_get_contents($URL);
$data = simplexml_load_string($response_xml_data);
I was finally able to reference the top level properties but am unable to get the properties of the Person. This is how I finally got it working if someone could help with the Person access or suggest a better way to do it.
$data->registerXPathNamespace('tns', 'http://www.example.com/api/person');
$LastName = $data->xpath('//tns:LastName ');
$TransmissionDate = $data->xpath('//tns:TransmissionDate');
echo $LastName[0];
echo "<br/>";
echo $TransmissionDate[0];
You need to keep prepending the namespace to your XPath query elements, like so:
//tns:People/tns:Person/tns:Name
That will give you all the Name elements inside Person, inside People.
$data = simplexml_load_string($response_xml_data);
$data->registerXPathNamespace('tns', 'http://www.example.com/api/person');
$LastName = $data->xpath('//tns:LastName ');
$TransmissionDate = $data->xpath('//tns:TransmissionDate');
$people = $data->xpath('//tns:People/tns:Person/tns:Name');
var_dump($people);
Demo
Result
array (size=2)
0 =>
object(SimpleXMLElement)[4]
public 0 => string 'John Doe' (length=8)
1 =>
object(SimpleXMLElement)[5]
public 0 => string 'Jane Doe' (length=8)

Getting XML data in PHP

I am trying to read XML data in PHP. The XML data is coming from an API whose link is the following: https://seekingalpha.com/api/sa/combined/AAPL.xml
I just need News Headline, News Link , Published Date and Author Name of the first five news from the API. To do this, I am using the following PHP code:
$note = "https://seekingalpha.com/api/sa/combined/".$symbolValue.".xml";
$xml=simplexml_load_file($note);
$jsonArray = array();
for ($i=0; $i<5; $i++) {
$newsHeadline = $xml->channel->item[$i]->title->__toString();
$newsLink = $xml->channel->item[$i]->link->__toString();
$publishedDate = $xml->channel->item[$i]->pubDate->__toString();
$authorName = $xml->channel->item[$i]->sa:author_name->__toString();
$temp = array('Title' => $newsHeadline, 'Link' => $newsLink,'Publish'=>$publishedDate,'Author'=>$authorName);
array_push($jsonArray,$temp);
}
$jsonNews = json_encode($jsonArray);
$completeData[9] = $jsonNews;
In the above code, $note contains the link to the API. The $symbolValue is the value which I am getting from the front end. My code works absolutely until I access the author name ie. The following line of code:
$authorName = $xml->channel->item[$i]->sa:author_name->__toString();
I am getting the following error:
Parse error: syntax error, unexpected ':' in /home/File/Path
It seems like I am not supposed to use the ":" for fetching the author name.
So, how do I get the user name and put it in the $temp such that the Tag for the author name is "Author"?
Please have a look at the API to get an idea about the XML file.
The children() method supports an argument for the namespace you want to read. This is required when you want to read elements which are not in the current/default namespace.
$xmldata = <<<'XML'
<?xml version="1.0"?>
<foobar xmlns:x="http://example.org/">
<abc>test</abc>
<x:def>content</x:def>
</foobar>
XML;
$xml = new Simplexmlelement($xmldata);
$other = $xml->children('http://example.org/');
var_dump((string)$other->def);
This will output the value "content", but using the expression $xml->def will not because that is not in the current/default namespace.
If you property contains for example a :, you could use curly braces
->{'sa:author_name'}
The values you are looking for are in the https://seekingalpha.com/api/1.0 namespace.
You could use the children of the SimpleXMLElement and add te namespace:
$authorName = (string)$xml->channel->item[$i]->children('https://seekingalpha.com/api/1.0')->{'author_name'};
Or you could use xpath.
$authorName = (string)$xml->channel->item[$i]->xpath('sa:author_name')[0];
For example:
$jsonArray = array();
for ($i = 0; $i < 5; $i++) {
$newsHeadline = $xml->channel->item[$i]->title->__toString();
$newsLink = $xml->channel->item[$i]->link->__toString();
$publishedDate = $xml->channel->item[$i]->pubDate->__toString();
$authorName = (string)$xml->channel->item[$i]->xpath('sa:author_name')[0];
// or xpath
// $authorName = (string)$xml->channel->item[$i]->children('https://seekingalpha.com/api/1.0')->{'author_name'};
$temp = array('Title' => $newsHeadline, 'Link' => $newsLink, 'Publish' => $publishedDate, 'Author' => $authorName);
array_push($jsonArray, $temp);
}
$jsonNews = json_encode($jsonArray);
print_r($jsonArray);
Will give you:
Array
(
[0] => Array
(
[Title] => Apple acknowledges iPhone X issue in some devices, plans fix
[Link] => https://seekingalpha.com/symbol/AAPL/news?source=feed_symbol_AAPL
[Publish] => Fri, 10 Nov 2017 12:04:42 -0500
[Author] => Brandy Betz
)
etc...

Cannot get XML structure right

I am working with XML and php. I am trying to get an array of PHP result to this XML format with two <customer> customers, I can get 1 but dont know how to do it for 2 customers in an array.
<?xml version="1.0"?>
<NewSLSCase>
<Identification CientNo="4xxx" CLientBatchNo="1" IJBatchNo="1" HubNo="201048" ClientEmailAddress1="etunimi.sukunimi#yritys.fi" ClientEmailAddress2="etunimi.sukunimi#yritys.fi"/>
<LedgerSet>
<Ledger ProductionUnit="04" LedgerNo="4xxxxx">
<CustomerSet>
<Customer No="123456" Name="Farhana" Address1="Myhouse" ZipCode="40100" City="Vantaa" LanguageCode="FIN" CountryCode="FI" VatNo="01011-111A" TypeCode="C"/>
<Customer No="123457" Name="Asiakas Anna" Address1="Asiakastie 2" ZipCode="00100" City=" Helsinki" LanguageCode="FIN" CountryCode="FI" VATNo="010111-111A" TypeCode="C"/>
</CustomerSet>
<InvoiceSet>
<Invoice InvoiceNo="123456"/>
<InvoiceHeader InvoiceHeaderType="L" InvoiceCustomerNo="123456" InvoiceCurrency="EUR" InvoiceDate="2011-04-08" InvoiceDueDate="2011-05-15" InvoiceAmount="57.00" ClientOCRReference="908000101800031186" InvoiceReferenceText3="150,00" InvoiceReferenceText4="Laskuille tulostuva" InvoiceReferenceText5="IBAN" InvoiceReferenceText6="BIC"/>
</InvoiceSet>
</Ledger>
</LedgerSet>
</NewSLSCase>
I wrote the codes for just getting one ` but adding another one is something I am truly not sure off.
Here is the array, did not copy the whole thing since its big, but I am using a small part of it for testing.
array(2) (
[0] => stdClass object {
ID => (string) 177835
currency => (string) Asiakas Anna
type => (string) Asiakastie 2
}
[1] => stdClass object {
ID => (string) 177840
Name=> (string) Farhana
Address=> (string) Myhouse
.....
Here is the whole XML format
$result = $this->invoice_page->getInvoiceByID('20241'); //this is the array
$xml = new DomDocument('1.0');
$xml->formatOutput = true;
$NewSLSCase = $xml->createElement("NewSLSCase");
$xml->appendChild($NewSLSCase);
$Identification = $xml->createElement("Identification");
$Identification->setAttribute("CientNo","4xxx");
$Identification->setAttribute("CLientBatchNo", "1");
$Identification->setAttribute("CLientBatchNo", "1");
$Identification->setAttribute("IJBatchNo", "1");
$Identification->setAttribute("HubNo", "201048");
$Identification->setAttribute("ClientEmailAddress1", "etunimi.sukunimi#yritys.fi");
$Identification->setAttribute("ClientEmailAddress2", "etunimi.sukunimi#yritys.fi");
$NewSLSCase->appendChild($Identification);
$LedgerSet = $xml->createElement("LedgerSet");
$NewSLSCase->appendChild($LedgerSet);
$Ledger = $xml->createElement("Ledger");
$Ledger->setAttribute("ProductionUnit","04");
$Ledger->setAttribute("LedgerNo", "4xxxxx");
$LedgerSet->appendChild($Ledger);
$CustomerSet = $xml->createElement("CustomerSet");
$Ledger->appendChild($CustomerSet);
$Customer = $xml->createElement("Customer");
$Customer->setAttribute("No","123456");
$Customer->setAttribute("Name", $result['Fullname']);
$Customer->setAttribute("Address1", $result['Address_street']);
$Customer->setAttribute("ZipCode", $result['Address_zip']);
$Customer->setAttribute("City",$result['Address_city']);
$Customer->setAttribute("LanguageCode", "FIN");
$Customer->setAttribute("CountryCode","FI");
$Customer->setAttribute("VatNo", "01011-111A");
$Customer->setAttribute("TypeCode","C");
$CustomerSet->appendChild($Customer);
$InvoiceSet = $xml->createElement("InvoiceSet");
$Ledger->appendChild($InvoiceSet);
$Invoice = $xml->createElement("Invoice");
$Invoice->setAttribute("InvoiceNo","123456");
$InvoiceSet->appendChild($Invoice);
$InvoiceHeader = $xml->createElement("InvoiceHeader");
$InvoiceHeader->setAttribute("InvoiceHeaderType", "L");
$InvoiceHeader->setAttribute("InvoiceCustomerNo","123456");
$InvoiceHeader->setAttribute("InvoiceCurrency", "EUR");
$InvoiceHeader->setAttribute("InvoiceDate","2011-04-08");
$InvoiceHeader->setAttribute("InvoiceDueDate", "2011-05-15");
$InvoiceHeader->setAttribute("InvoiceAmount","57.00");
$InvoiceHeader->setAttribute("ClientOCRReference", "908000101800031186");
$InvoiceHeader->setAttribute("InvoiceReferenceText3","150,00");
$InvoiceHeader->setAttribute("InvoiceReferenceText4","Laskuille tulostuva");
$InvoiceHeader->setAttribute("InvoiceReferenceText5",$result['IBAN']);
$InvoiceHeader->setAttribute("InvoiceReferenceText6",$result['BIC']);
$InvoiceSet->appendChild($InvoiceHeader);
echo "<xmp>".$xml->saveXML()."</xmp>";
What the above code, gives me is this
<?xml version="1.0"?>
<NewSLSCase>
<Identification CientNo="4xxx" CLientBatchNo="1" IJBatchNo="1" HubNo="201048" ClientEmailAddress1="etunimi.sukunimi#yritys.fi" ClientEmailAddress2="etunimi.sukunimi#yritys.fi"/>
<LedgerSet>
<Ledger ProductionUnit="04" LedgerNo="4xxxxx">
<CustomerSet>
<Customer No="123456" Name="Farhana" Address1="Myhouse" ZipCode="40100" City="Vantaa" LanguageCode="FIN" CountryCode="FI" VatNo="01011-111A" TypeCode="C"/>
</CustomerSet>
<InvoiceSet>
<Invoice InvoiceNo="123456"/>
<InvoiceHeader InvoiceHeaderType="L" InvoiceCustomerNo="123456" InvoiceCurrency="EUR" InvoiceDate="2011-04-08" InvoiceDueDate="2011-05-15" InvoiceAmount="57.00" ClientOCRReference="908000101800031186" InvoiceReferenceText3="150,00" InvoiceReferenceText4="Laskuille tulostuva" InvoiceReferenceText5="IBAN" InvoiceReferenceText6="BIC"/>
</InvoiceSet>
</Ledger>
</LedgerSet>
</NewSLSCase>
I have no clue how to add a foreach to get two customers information.
Use foreach loop through customers:
foreach ($customersArray as $customerData) {
$Customer = $xml->createElement("Customer");
$Customer->setAttribute("No",$customerData->ID);
//set all attributes like that
$CustomerSet->appendChild($Customer);
}

Return parent node after string search in XML - PHP

I have an XML file like so:
<GenResponse>
<Detail1></Detail1>
<Detail2></Detail>
<DataNodes>
<DataNode>
<NodeDetails1>
<node4>Parrot Musky Truck Moo</node4>
<node5>Tinker Singer Happy Fool</node5>
<node6>
<FurtherDetails>
<Node>Musky</Node>
<Node>Lorem Ipsum</Node>
</FurtherDetails>
</NodeDetails1>
<NodeDetails2>ID</NodeDetails2>
</DataNode>
<DataNode>
<NodeDetails1>
<node4>Sky Star Panet Shoe</node4>
<node5>Rusky Husky Musky Boo</node5>
</NodeDetails1>
<NodeDetails2>ID</NodeDetails2>
</DataNode>
</DataNodes>
</GenResponse>
I would like to know how I would inject a search string "Musky" to a PHP function and get back <DataNode>...</DataNode> & <DataNode>...</DataNode> back?
Essentially I would like to search a huge XML file for a string and return all the DataNode's which contain the string back.
If this is possible with SimpleXML it would be great. Else any other solution is also fine.
EDIT: Notice how "Musky" can be in different nodes under <DataNode>
use
$xmlStr = file_get_contents('data/your_XML_File.xml');
$xml = new SimpleXMLElement($xmlStr);
// seach records by tag value:
// find nodes with text
$res = $xml->xpath("node2[contains(., 'Musky')]");
print_r($res);
//For testing purpost just copy paste following code in editor , For testing , I didnt use separate xml file.
<?php
//$xmlStr = file_get_contents('test.xml');
$xmlStr = '<node1>
<node2>
<node3>
<node4>Parrot Singer Truck Moo</node4>
<node5>Tinker Musky Happy Fool</node5>
</node3>
<node7>ID</node7>
</node2>
<node2>
<node3>
<node4>Sky Star Panet Shoe</node4>
<node5>Rusky Husky Musky Boo</node5>
</node3>
<node7>ID</node7>
</node2>
</node1>';
$xml = new SimpleXMLElement($xmlStr);
// seach records by tag value:
// find nodes with text
$res = $xml->xpath("node2[contains(., 'Musky')]");
echo "<pre>";
print_r($res);
?>
It gives proper output , i tried
Array
(
[0] => SimpleXMLElement Object
(
[node3] => SimpleXMLElement Object
(
[node4] => Parrot Singer Truck Moo
[node5] => Tinker Musky Happy Fool
)
[node7] => ID
)
[1] => SimpleXMLElement Object
(
[node3] => SimpleXMLElement Object
(
[node4] => Sky Star Panet Shoe
[node5] => Rusky Husky Musky Boo
)
[node7] => ID
)
)
Use this code and you can find your search word.I have made it a function just pass your keyword and you will get your result,
function findWord($findVar)
{
$catalog = simplexml_load_file("xmlfile.xml");
$category = $catalog->node2;
$found = 0;
foreach($category as $c)
{
foreach($c->node3 as $node3)
{
$node4 = (string) ($node3->node4);
$node5 = (string) ($node3->node5);
if (stripos(strtolower($node4),strtolower($findVar)))
{
echo 'Found!!'.'<br/>';
$found++;
}
if (stripos(strtolower($node5),strtolower($findVar)))
{
echo 'Found!!'.'<br/>';
$found++;
}
}
if (stripos(strtolower((string)$c->node7),strtolower($findVar)))
{
echo 'Found!!'.'<br/>';
$found++;
}
}
if ($found == 0)
{
echo "No result";
}
}
$findVar = 'Musky';
findWord($findVar);

How to Parse the ajax script in DOM Parser?

I parsing scores from http://sports.in.msn.com/football-world-cup-2014/south-africa-v-brazil/1597383
I able to parse all the attributes. But I can't able to parse the time.
I Used
$homepages = file_get_html("http://sports.in.msn.com/football-world-cup-2014/south-africa-v-brazil/1597383");
$teama = $homepages->find('span[id="clock"]');
Kindly help me
Since the that particular site is loading the values dynamically (thru AJAX request), you cant really parse the value upon initial load.
<span id="clock"></span> // this tends to be empty initial load
Normal scrapping:
$homepages = file_get_contents("http://sports.in.msn.com/football-world-cup-2014/south-africa-v-brazil/1597383");
$doc = new DOMDocument();
#$doc->loadHTML($homepages);
$xpath = new DOMXPath($doc);
$query = $xpath->query("//span[#id='clock']");
foreach($query as $value) {
echo $value->nodeValue; // the traversal is correct, but this will be empty
}
My suggestion is instead of scraping it, you will need to have to access it thru a request also, since it is a time (of course, as the match goes on this will change and change until the game has ended). Or you can also use their request.
$url = 'http://sports.in.msn.com/liveplayajax/SOCCERMATCH/match/gsm/en-in/1597383';
$contents = file_get_contents($url);
$data = json_decode($contents, true);
echo '<pre>';
print_r($data);
echo '</pre>';
Should yield something like (a part of it actually):
[2] => Array
(
[Code] =>
[CommentId] => -1119368663
[CommentType] => manual
[Description] => FULL-TIME: South Africa 0-5 Brazil.
[Min] => 90'
[MinExtra] => (+3)
[View] =>
[ViewHint] =>
[ViewIndex] => 0
[EditKey] =>
[TrackingValues] =>
[AopValue] =>
)
You should get the 90' by using foreach. Consider this example:
foreach($data['Commentary']['CommentaryItems'] as $key => $value) {
if(stripos($value['Description'], 'FULL-TIME') !== false) {
echo $value['Min'];
break;
}
}
Should print: 90'

Categories