simplexml_load_file omitting 00 from xml to csv - php

I have an XML
Sample:
<?xml version="1.0" encoding="utf-8"?>
<StockValues>
<Product>
<Product_Code>00380</Product_Code>
<Available_Stock>200</Available_Stock>
<Due_Date>2013-10-13</Due_Date>
</Product>
<Product>
<Product_Code>00429</Product_Code>
<Available_Stock>200</Available_Stock>
<Due_Date>2013-11-14</Due_Date>
</Product>
<Product>
<Product_Code>00495</Product_Code>
<Available_Stock>200</Available_Stock>
<Due_Date>N/A</Due_Date>
</Product>
<Product>
<Product_Code>0122</Product_Code>
<Available_Stock>200</Available_Stock>
<Due_Date>N/A</Due_Date>
</Product>
<Product>
<Product_Code>0190</Product_Code>
<Available_Stock>200</Available_Stock>
<Due_Date>2013-10-16</Due_Date>
</Product>
<Product>
<Product_Code>052A</Product_Code>
<Available_Stock>200</Available_Stock>
<Due_Date>N/A</Due_Date>
</Product>
<Product>
<Product_Code>052B</Product_Code>
<Available_Stock>200</Available_Stock>
<Due_Date>2013-10-09</Due_Date>
</Product>
<Product>
<Product_Code>052BK</Product_Code>
<Available_Stock>200</Available_Stock>
<Due_Date>2013-09-28</Due_Date>
</Product>
I am using simplexml_load_file to convert to a CSV. It works great but 2 problems. Firstly my product codes starting with 00 lose the 00 in generating CSV. Therefore I somehow need to keep this is as a text field.
Secondly, I would like to put column headings in here also.
This is the code I have adapted so far:
<?php
$filename='test.csv';
if (! file_exists($filename))
{
echo "There's no test file";
}
else
{
echo "There's 1a test file !";
unlink($filename);
}
echo '<br />';
if( ! $xml = simplexml_load_file('1feed2.xml') )
{
echo 'unable to load XML file';
}
else
{
foreach( $xml as $product_record )
{
$prodarray = "\"$product_record->Product_Code\"".","."$product_record->Available_Stock".",END\n";
echo $prodarray;
//echo '<br />';
file_put_contents($filename,$prodarray,FILE_APPEND);
echo "line written <br />";
}
}
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize($filename));
fclose($handle);
print $contents;
?>
Does anyone know what I can do to fix this?
It currently generates a CSV which is great but just missing the above bits.

Let's assume that you need to add 01, 02 and 03 values in your csv file.
While creating your csv, if you just pass 01,02,03 to the csv file the 0 value won't be displayed when you open the csv file.
To solve this problem just append the file like '01,'02,'03. And the zeros will be displayed when you open the file.
Just remember to add ' character before the column value.
Edit
You haven't mentioned if the column names are fixed or whether it depends on your xml.
I'll try to answer this on the assumption that your column names don't change.
Create a function which appends your data to a csv file. (Although this is not necessary.)
function addRowToCsv($data, $filename){
file_put_contents($filename,$data,FILE_APPEND);
}
In order to add the column names just call the function before the foreach loop.
addRowToCsv("Product Code, Available Stock, Status\n");
See the below updated code.
<?php
$filename='test.csv';
if (! file_exists($filename))
{
echo "There's no test file";
}
else
{
echo "There's 1a test file !";
unlink($filename);
}
echo '<br />';
$xml = simplexml_load_file('1feed2.xml');
//avoid unnecessary else and elseif statments.
if(!$xml){
echo 'unable to load XML file';
exit;
}
//adding column names
addRowToCsv("Product Code, Available Stock, Status\n");
foreach($xml as $product_record){
$product_code = (int) $product_record->Product_Code;
$available_stock = (int) $product_record->Available_Stock;
//Add ' character before the column value
$csv_line = "'$product_code,'$available_stock,END\n";
addRowToCsv($csv_line);
}
$handle = fopen($filename, "rb");
if($handle){
$contents = fread($handle, filesize($filename));
fclose($handle);
print $contents;
}
function addRowToCsv($data, $filename){
file_put_contents($filename,$data,FILE_APPEND);
}
?>

Related

PHP gzread, gzfile, gzopen, etc.. all strip tags off of XML and return only the values [duplicate]

This question already has answers here:
How to echo XML file in PHP
(10 answers)
Output raw XML using php
(5 answers)
Closed 1 year ago.
I have .gz files that contain xml files. I've tried every combination of all the different things shown in the code below. Any time one of the gz..... methods "works" it returns the values contained inside the XML files will all the tags and metadata gone. For example, if the xml file looks like this:
<?xml version="1.0" encoding="UTF-8" ?>
<tag1>
<taga>
This
</taga>
<tagb>
is the stuff
</tagb>
</tag1>
<tag2>
<taga>
I get but only
</taga>
<tagb>
This
</tagb>
</tag2>
What I get is:
This is the stuff I get but only This
Here's the code:
<?php
$mailfileObj->zipfile = 'path/to/gzfile.gz'; //ignore the fact that it says zipfile, it is a .gz file
try{
$opengzfile = gzopen($mailfileObj->zipfile, "r");
$contents = gzread($opengzfile, filesize($mailfileObj->zipfile));
gzclose($opengzfile);
var_dump($contents);
echo '<br>';
//$opengzfile = fopen($mailfileObj->zipfile, "r");
//$contents = fread($opengzfile, filesize($mailfileObj->zipfile));
//fclose($opengzfile);
//$contents = file_get_contents($mailfileObj->zipfile);
$contents2 = '';
$lines = gzfile($mailfileObj->zipfile);
foreach ($lines as $line) {
echo $line;
$contents2 = $contents2.$line;
}
//var_dump($contents);
//echo '<br>';
//var_dump($contents);
//echo $contents . '<br><br>';
//$xmlfilegz = $mailfileObj->filename.'.xml';
//$openxmlfile = fopen($xmlfilegz, "w");
//fwrite($openxmlfile, $contents);
//fclose($openxmlfile);
$opengzfile = fopen($mailfileObj->zipfile, "r");
$contents2 = fread($opengzfile, filesize($mailfileObj->zipfile));
fclose($opengzfile);
//$contents2 = file_get_contents($mailfileObj->zipfile);
//$contents2 = gzdecode($contents);
$contents2 = gzinflate($contents);
//$contents2 = gzuncompress($contents);
var_dump($contents2);
}
catch(Exception $e){
echo 'Caught exception: ' . $e->getMessage() . '<br>';
}
?>
What is wrong here? What am I missing?
Thank you.
You're putting the XML in an HTML web page, so the browser is interpreting the XML tags as HTML tags.
Use htmlentities() to encode them so they'll be rendered literally.
foreach ($lines as $line) {
echo htmlentities($line);
$contents2 = $contents2.$line;
}
You might want to show this in a <pre> block so the newlines and indentation will be preserved.

Differences between two xml strings using php

I'm trying to compare and check the differences between two xml strings but my code is not detecting any changes in xml strings!
for ex my first string contains :
<Result>
<pid>10</pid>
<DocID>29</DocID>
<Response>True</Response>
<DocID>60<DocID>
<Blvd_Name>dfdfdfdfd</Blvd_Name>
<Alley_Name>dfd</Alley_Name>
<Plate_Number>654654</Plate_Number>
<Post_Code>654654654</Post_Code>
<Phone_1>654654</Phone_1>
<Phone_2>654654564</Phone_2>
<Fax>2323232</Fax>
<Website>ewewew</Website>
<Mobile_No>23232323232</Mobile_No>
<Information>
<Info>
<National_Code>106397854</National_Code>
<Start_Activity_Date>2015-12-22 00:00:00</Start_Activity_Date>
<End_Activity_Date>2016-01-03 00:00:00</End_Activity_Date>
</Info>
</Information>
<Service_Times>
<Service_Time>15:30 - 17:45</Service_Time>
</Service_Times>
</Result>
the second string is :
<Result>
<pid>10</pid>
<DocID>29</DocID>
<Response>True</Response>
<DocID>60<DocID>
<Blvd_Name>dfdfdfdfd</Blvd_Name>
<Alley_Name>dfd</Alley_Name>
<Plate_Number>654654</Plate_Number>
<Post_Code>654654654</Post_Code>
<Phone_1>11111</Phone_1>
<Phone_2>6546111154564</Phone_2>
<Fax>11111</Fax>
<Website>11111</Website>
<Mobile_No>11111</Mobile_No>
<Information>
<Info>
<National_Code>106397854</National_Code>
<Start_Activity_Date>2015-12-22 8:01:50</Start_Activity_Date>
<End_Activity_Date>2016-01-03 11:20:10</End_Activity_Date>
</Info>
</Information>
<Service_Times>
<Service_Time>15:30 - 17:45</Service_Time>
</Service_Times>
</Result>
as you can see there are some differences in the values of the objects!
I've tried simplexmlload and then array_diff and jason encode and decode and comparing the jason but there was not chance to detect the differences.
any suggestion how to accomplish that ?
my array diff code :
$result = array_diff($Data1, $Data2);
if(empty($result)){
// the XML documents are the same
$res = "No changes";
} else {
// they are different
$res = "There are Some changes";
}
You can leave the data as raw text ane see the difference by using the following
<?php
$difference = xdiff_string_diff($Data1, $Data2);
Ok I solved the problem using simple if comparison method and it worked.
I first opened two xml files and then i copared them using method below, if i change a value/structure in second xml file it gives me "there are some changes".
$file = './Result.xml';
if (file_exists($file)) {
$Data = file_get_contents($file);
} else {
exit('Failed to open ' . $file);
}
$file2 = './Result2.xml';
if (file_exists($file2)) {
$Data2 = file_get_contents($file2);
} else {
exit('Failed to open ' . $file2);
}
if ($Data === $Data2) {
// the XML documents are the same
$res = "No changes";
} else {
// they are different: print the reason why
$res = "There are Some changes";
}

can't download xml without 2-3 spaces at start of the document

I have this in my php code
header('Content-disposition: attachment; filename="'.$filename.'"');
header('Content-type: "text/xml"; charset="utf8"');
readfile($filename);
and my file after download
<?xml version="1.0" encoding="UTF-8"?>
<root>
has 2 or 3 spaces in front of the document , and I can't find a solution
And this is an error when i open the file:
This page contains the following errors:
error on line 1 at column 6: XML declaration allowed only at the start of the document
Below is a rendering of the page up to the first error.
and the xml file from the server is correct
the function that writes the file:
public function toXML($filename){
$qr = mysql_query("select * from passwords where user = '".encrypt($_SESSION['username'],$key)."'");
$xml = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$xml .= "<root>";
$xml .= "\n";
if (!$qr) {
die('Invalid query: ' . mysql_error());
}
if(mysql_num_rows($qr)>0)
{
while($result_array = mysql_fetch_assoc($qr))
{
$xml .= '<passwords>';
$xml .= "\n";
foreach($result_array as $key => $value)
{
$xml .= "<$key>";
$xml .= "$value";
$xml .= "</$key>";
$xml .= "\n";
}
$xml.="</passwords>\n";
}
}
$xml .= '</root>';
$fp = fopen($filename,"w");
fputs($fp,$xml);
fclose($fp);
return true;
}
and in the other php file
if(!$r->toXML($filename))
$msg = 'Failed to export';
else{
$text = file_get_contents($filename);
$bom = pack('H*','EFBBBF');
$text = preg_replace("/^$bom/", '', $text);
header('Content-disposition: attachment; filename="'.$filename.'"');
header('Content-type: "text/xml"; charset="utf8"');
echo $text;
exit();
}
the file from server ( the $filename file )
<?xml version="1.0" encoding="UTF-8"?>
<root>
<passwords>
<id>8</id>
<title>vbghjbhv</title>
<account>o0H0uTtsOFCYHTpiZZ2/J78W/Z+xU10nx5AUZdcUvdU=</account>
<password>2vOF9Kp2p88IbbIuHcFJeaOc1VJi40KkrAtPIEV5exg=</password>
<url>jhbvgi</url>
<user>2PTpbCnciq+dbuEcyP6v6tZxrQeXcJfRl33YfQO3aFk=</user>
<category>Business</category>
<note>ghujhvgty</note>
</passwords>
</root>
One solution would be to store the file in a variable,
then use trim() before outputting the contents of the file.
$file = file_get_contents($filename);
echo trim($file);
First, check that your file on which you are working is being saved at proper charset (UTF-8 without BOM).
Second, we do not see actual filled contents of $filename. Let's say they are in $contents variable. Probably you filled it like this:
$contents .= '
... something ';
Make sure you get rid of blank lines while populating and write it like this:
$contents .= '... something ';

Adding xml node on top of file or reverse the loop

I am using xml. Reading the xml-document works fine, adding nodes works fine to but I want the node to add on top of the xml file. Is this possible or is this a nogo?
The reason I want this is because when I display the xml file I want the last added node, displayed as the newest one, on top.
I display the xml with this loop:
foreach($xml->xpath("//user[#id='12345678']") as $user){
foreach($user->children() as $action => $data){
echo"<li>";
echo $data->content;
echo $data->date;
echo"</li>";
}
}
If there is a way to reverse the loop or another way I'm fine with that to, it doesn't have to be adding the first node on top. Below are the file how I add the node and the structure of the xml-file.
Does anyone have an idea how to solve this?
addxml.php
<?php
$file = "actielijst.xml";
$fp = fopen($file, "rb") or die("cannot open file");
$str = fread($fp, filesize($file));
$xml = new DOMDocument();
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$xml->loadXML($str) or die("Error");
// get document element
echo "<xmp>OLD:\n". $xml->saveXML() ."</xmp>";
$root = $xml->documentElement;
$content = $xml->createElement("content");
$contentText = $xml->createTextNode("Nieuwe Factuur Mei");
$content->appendChild($contentText);
$date = $xml->createElement("date");
$dateText = $xml->createTextNode("23-12-2010");
$date->appendChild($dateText);
$action = $xml->createElement("action");
$action->appendChild($date);
$action->appendChild($content);
$root->appendChild($action);
$xml->save("actielijst.xml") or die("Error");
?>
actielijst.xml
<?xml version="1.0"?>
<userid>
-------> Insert new action here <------
<action>
<date>23-01-2010</date>
<content>nieuwe factuur</content>
</action>
<action>
<date>23-01-2010</date>
<content>karten op 01-02</content>
</action>
</userid>
You can use xpath to capture every parent node (action in your case) and then reverse the array...
$users_arr = array_reverse($xml->xpath("action"));
Now you can loop through this array!
This will helps
<?php
$file = "actielijst.xml";
$fp = fopen($file, "rb") or die("cannot open file");
$str = fread($fp, filesize($file));
$xml = simplexml_load_string($str);
$action = $xml->addChild('action');
$action->addChild('content','sundar');
$action->addChild('date','23-12-2010');
header('content-type: application/xml');
echo $xml->saveXML();

PHP - XML to CSV conversion issue

I really need some help on an issue: I'm converting an XML to CSV using a PHP script, but the XML contains some + signs and I don't know how to remove them from the CSV.
This is the XML file structure:
<PRICES>
<PRICE>
<WIC>HDE0AAFGRBOX</WIC>
<STOCK>100+</STOCK>
<MY_PRICE>219.00</MY_PRICE>
</PRICE>
</PRICES>
This is the script I use:
<?
$filexml='stock.xml';
if (file_exists($filexml)) {
$xml = simplexml_load_file($filexml);
$f = fopen('stock.csv', 'w')
foreach($xml->PRICES->PRICE as $price) {
fputcsv($f, get_object_vars($price),',','"');
}
fclose($f);
}
?>
The script works fine and the CSV file is good, but because I'm a noob with PHP I don't know how to remove the "+" sign.
Any help will be greatly appreciated.
Thanks in advance!
You could try to trim the chars you want to be removed (the '+' char):
foreach($xml->PRICES->PRICE as $price) {
$price->STOCK = trim($price->STOCK, "+");
fputcsv($f, get_object_vars($price),',','"');
}
Try to use str_replace :
$filexml='stock.xml';
if (file_exists($filexml)) {
$xml = simplexml_load_file($filexml);
$f = fopen('stock.csv', 'w')
foreach($xml->PRICES->PRICE as $price) {
$price->STOCK = str_replace("+","",$price->STOCK);
fputcsv($f, get_object_vars($price),',','"');
}
fclose($f);
}

Categories