How to load xml data with namespace - php

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)

Related

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...

Save xslt form in mysql using zend 1.12

I want to save xml document in mysql database as below:
$_docId= $this->getRequest()->getParam('docId', 0);
$_slmData = '<SLM_form_v2 id="slmform"><group_1_1><section1_1/><name1_1>sdfds</name1_1>
enter code here<localname1_2/><selectcountry_1_3>Algeria</selectcountry_1_3></group_1_1>
enter code here<group_1_2><main_doc/><name_doc1>gdgf gfh f</name_doc1><sex_doc1>Male
</sex_doc1><name_institution_1>fsdgdfg</name_institution_1><address_institution_1>gdgfdgfd
</address_institution_1>....';
$_docMapper = new Model_Mapper_XMLDoc();
$_docModel = new Model_XMLDoc();
$_docModel ->doc_data = Zend_Json::encode($_docData);
if ($_docId != 0) {
$_docModel->id = $_docId;
$_docMapper->update($_docModel->toArray(), 'id = ' . $_docId);
$_action = 'update';
} else {
$_docMapper->insert($_docModel->toArray());
$_lastId = $_docMapper->getAdapter()->lastInsertId(); //gets the id of the last inserted record
$_action = 'add';
}
$this->_helper->json->sendJson(array(
'message' => 'success',
'id' => $_lastId,
'action' => $_action
));
It is stored in the db:
INSERT INTO crpcoreix.tbl_xml_doc (slm_data, web_gis_fk) VALUES ('"<SLM_form_v2 id=\\"slmform\\"><group_1_1><section1_1\\/><name1_1>sdfds<\\/name1_1><localname1_2\\/><selectcountry_1_3>Algeria<\\/selectcountry_1_3><\\/group_1_1><group_1_2><main_doc\\/><name_doc1>gdgf gfh f<\\/name_doc1><sex_doc1>Male<\\/sex_doc1><name_institution_1>fsdgdfg<\\/name_institution_1><address_institution_1>gdgfdgfd gdgf<\\/address_institution_1>...', null);
When I'm trying to read the data from the database and display the encoded xml tags the output miss the first part ("<SLM_form_v2 id=\\"slmform\\"><group_1_1><section1_1\\/><name1_1>...) the first part
Array
(
[id] => 1
[xml_data] => "sdfds<\/name1_1>Algeria<\/selectcountry_1_3>...'
[web_gis_fk] =>
)
Please advice how to fix and if there is a better way to store xml documents in database.
Thanx,
first is first you need to double check your given xml syntax, whether its correct or not.
Zend_Json includes a static function called Zend_Json::fromXml(). so
you would better manage to use it instead of Zend_Json::encode when
you encode XML
This function will generate JSON from a given XML input.
This function takes any arbitrary XML string as an input parameter. It also takes an optional Boolean input parameter to instruct the conversion logic to ignore or not ignore the XML attributes during the conversion process.
If this optional input parameter is not given, then the default behavior is to ignore the XML attributes. This function call is made as shown below:
$jsonContents = Zend_Json::fromXml($xmlStringContents, true);
Give it a try but again check your XML syntax

How to append new element in JSON file without get all data of this file in PHP

i need to append some elements to json file
this is my code:
routes.php (stage1)
$array = ['id' => '1', 'number' => '123123', 'name' => 'ahmed'];
$json_array = json_encode($array);
Storage::append('test.json', json_encode(['user_name' => 'ahmedsk']));
test.json
{"user_name":"ahmedsk"}
{"id":"1","number":"24142","username":"ahmedsk"}
but when i make print_r() for $result it's not feedback
routes.php (stage2)
$result = Storage::get('test.json');
print_r($result);
With knowing i don't need to use the method of get all data from JSON file and edited it and resave it in file.
Thanks
The question is some how vague.
if you need to print the json file as an array this is what you need :
routes.php (stage2)
$result = Storage::get('test.json');
print_r(json_decode("[" . preg_replace("/\n+/",",",$result) . "]"));
test :
https://eval.in/499591

PHP Processing stream_get_contents into an array

I am having troubles converting a string which contains tab delimited CSV output
into an array. While using the following code :
$data = stream_get_contents($request->getShipmentReport());
I get back data as following:
Date Shipped Comments Feedback Arrived on Time
5/11/15 2 comment response Yes
Now I would like to process this data into an array with the returned headers(line 1) as the index containing the value for each line which follows after that.
I am trying to end up with something like this :
$line['Date'] = 5/11/15
$line['Shipped'] = 2
$line['Feedback'] = response
$line['Arrived on Time'] yes
What would be the best way to achieve this ?
I recommend using a library for handling CSV for example the CSV-Package by The League of Extraordinary Packages
You can pass your data and start working with array structures right away:
$csvString = stream_get_contents($request->getShipmentReport());
$csvReader = \League\Csv\Reader::createFromString($csvString);
$data = $csvReader->fetchAssoc(
array('Date', 'Shipped', 'Comments', 'Feedback', 'Arrived on Time')
);
// Or since line 0 contains header
$data = $csvReader->fetchAssoc(0); // 0 is offset of dataset containing keys
Now your data should be in a structure like:
$data = array(
array(
'Date' => '5/11/15',
'Shipped' => '2',
...
),
array(
...
)
);
You can even filter out specific datasets and all kinds of fancy stuff. Just check the documentation I linked to.
League CSV reader gives me a bad result. I use this instead:
$csvReportString = stream_get_contents($request->getReport());
$csvReportRows = explode("\n", $csvReportString);
$report = [];
foreach ($csvReportRows as $c) {
var_dump($c);
if ($c) { $report[] = str_getcsv($c, "\t");}
}
var_dump($report);

Create duplicate tags on NuSOAP

I'm having some troubles with NuSOAP trying to send duplicate tags. This is the code i need to send :
<PartNumbers>
<string>string1</string>
<string>string2</string>
</PartNumbers>
I'm doing the call with this code:
$pn[] = 'APPSP2101V2';
$pn[] = 'ME665Y/A';
$PartNumbers = array( 'PartNumbers' => array('string' => $pn));
$result = $client->call('GetDataSheetsLastUpdate', $PartNumbers );
I'm sending those two PartNumbers but instead of send the two codes it's sending the last one "ME665Y/A"
Also if i try
$PartNumbers = array( 'PartNumbers' => array('string' => 'APPSP2101V2', 'string' => 'ME665Y/A'));
$result = $client->call('GetDataSheetsLastUpdate', $PartNumbers );
Only send the last string.
How can i make an array with the same keys but different value to make the XML look like in the beggining of the question.
Thank you in advance to all
With the following code:
$pn[] = 'APPSP2101V2';
$pn[] = 'ME665Y/A';
$PartNumbers = array( 'PartNumbers' => array('string' => $pn));
$result = $client->call('GetDataSheetsLastUpdate', $PartNumbers );
Works perfect , the problema was in the webservice.. if the P/N isn't correct only return the P/N with information on it.

Categories