Can't read large XML file from PHP - php

I have a huge XML file (114 KB/1719 lines; see the error message below why I say huge) and I try to read it as I have done with two similar files before.
The other two files load normally and are of comparable size the only difference being that the file in question contains Arabic text. So here is the PHP code:
$doc3 = new DOMDocument('1.0', 'utf-8');
$doc3->load($masternumber.'.xml');
And the error is:
Warning: DOMDocument::load() [domdocument.load]: Excessive depth in document: 256 use XML_PARSE_HUGE option in file: ...
Then $doc3 doesn't load the file. So I modified the code:
$doc3->load($masternumber.'.xml', "LIBXML_PARSEHUGE");
And I end-up with another warrning:
Warning: DOMDocument::load() expects parameter 2 to be long, string given in...
$doc3 is empty again.
What is wrong with it? The other files contain the same text in other languages and load properly but not this one? I am using PHP 5.3.9.

Use a constant, not a string.
$doc3->load($masternumber.'.xml', LIBXML_PARSEHUGE);
See the DOMDocument::load() documentation for complete details. The second parameter is a long integer representing the selected options from the list of constants.
Incidentally, if you need multiple options for any reason, it is done by combining them with the bitwise OR operator |
// Multiple options OR'd together...
// Just FYI, not specific to your situation...
$doc3->load($masternumber.'.xml', LIBXML_PARSEHUGE|LIBXML_NSCLEAN);

Related

PHPSpreadsheet generates an error "Wrong number of arguments for INDEX() function: 5 given, between 1 and 4 expected"

I tried to enter the following code in my excel formula bar directly
=INDEX($E$4:$E$132,AGGREGATE(15,6,ROW($1:$30) / ($J$4:$J$132=M4), COUNTIF($M$4:M4, M4))) and works perfectly fine (the left column on the pic below).
But if I'm using my web application to generate an excel report file (PHP, using CodeIgniter and Laravel). It displays an error "'Wrong number of arguments for INDEX() function: 5 given, between 1 and 4 expected'"
Here's my sample code snippet:
$code = "=INDEX(\$E\$4:\$E\$$occurance, AGGREGATE(15,6,ROW(\$1:\$$occurance) / (\$J\$4:\$J\$$occurance=M$top_cell), COUNTIF(\$M\$4:M$top_cell, M$top_cell)))";
$ews2->setCellValue("L$top_cell", $code);
I also have tried to use the setValueExplicit method but causes the excel file to NOT precalculate the code, it reads the code as a string
$ews2->setCellValueExplicit("L$top_cell", $code, DataType::TYPE_STRING);
NOTE TYPE_STRING is provided because if TYPE_FORMULA is also used, the same output mentioned at the top occurs
Here's what it looks like using the setCellValueExplicit
May I know the right solution or quick fix for this? Thank you very much in advance!
I have found out that the PHPSpreadsheet library for PHP is yet to allow the usage of the AGGREGATE() and complicated formulas/functions, so I had found another way around
By using this excel code
=INDEX(E$2:E$38,IF(M4=M3,MATCH(L3,E$2:E$38,0),0)+MATCH(M4,OFFSET(J$2,IF(M4=M3,MATCH(L3,E$2:E$38,0),0),0,COUNT(J$2:J$38)-IF(M4=M3,MATCH(L3,E$2:E$38,0),0),1),0))
I was able to traverse through my entire range and make sure that no duplicate publication names would appear
This is in relation with the my other question -> Excel - Getting the 2nd or nth matched string from your corresponding data

binary safe write on file with php to create a DBF file

I need to split a big DBF file using php functions, this means that i have for example 1000 records, i have to create 2 files with 500 records each.
I do not have any dbase extension available nor i can install it so i have to work with basic php functions. Using basic fread function i'm able to correctly read and parse the file, but when i try to write a new dbf i have some problems.
As i have understood, the DBF file is structured in a 2 line file: the first line contains file info, header info and it's in binary. The second line contains the data and it's plain text. So i thought to simply write a new binary file replicating the first line and manually adding the first records in the first file, the other records in the other file.
That's the code i use to parse the file and it works nicely
$fdbf = fopen($_FILES['userfile']['tmp_name'],'r');
$fields = array();
$buf = fread($fdbf,32);
$header=unpack( "VRecordCount/vFirstRecord/vRecordLength", substr($buf,4,8));
$goon = true;
$unpackString='';
while ($goon && !feof($fdbf)) { // read fields:
$buf = fread($fdbf,32);
if (substr($buf,0,1)==chr(13)) {$goon=false;} // end of field list
else {
$field=unpack( "a11fieldname/A1fieldtype/Voffset/Cfieldlen/Cfielddec", substr($buf,0,18));
$unpackString.="A$field[fieldlen]$field[fieldname]/";
array_push($fields, $field);
}
}
fseek($fdbf, 0);
$first_line = fread($fdbf, $header['FirstRecord']+1);
fseek($fdbf, $header['FirstRecord']+1); // move back to the start of the first record (after the field definitions)
first_line is the variable the contains the header data, but when i try to write it in a new file something wrong happens and the row isn't written exactly as it was read. That's the code i use for writing:
$handle_log = fopen($new_filename, "wb");
fwrite($handle_log, $first_line, strlen($first_line) );
fwrite($handle_log, $string );
fclose($handle_log);
I've tried to add the b value to fopen mode parameter as suggested to open it in a binary way, i've also taken a suggestion to add exactly the length of the string to avoid the stripes of some characters but unsuccessfully since all the files written are not correctly in DBF format. What can i do to achieve my goal?
As i have understood, the DBF file is structured in a 2 line file: the
first line contains file info, header info and it's in binary. The
second line contains the data and it's plain text.
Well, it's a bit more complicated than that.
See here for a full description of the dbf file format.
So it would be best if you could use a library to read and write the dbf files.
If you really need to do this yourself, here are the most important parts:
Dbf is a binary file format, so you have to read and write it as binary. For example the number of records is stored in a 32 bit integer, which can contain zero bytes.
You can't use string functions on that binary data. For example strlen() will scan the data up to the first null byte, which is present in that 32 bit integer, and will return the wrong value.
If you split the file (the records), you'll have to adjust the record count in the header.
When splitting the records keep in mind that each record is preceded by an extra byte, a space 0x20 if the record is not deleted, an asterisk 0x2A if the record is deleted. (for example, if you have 4 fields of 10 bytes, the length of each record will be 41) - that value is also available in the header: bytes 10-11 - 16-bit number - Number of bytes in the record. (Least significant byte first)
The file could end with the end-of-file marker 0x1A, so you'll have to check for that as well.

Backtrace to mysql_close warnings in PHP

I'm redoing a large portion of my website to use older mysql_* extensions because they execute faster. Yes I know people say its not a good idea to use older extensions, but I need to go for speed since this code is part of the back-end operations to my website and I want to serve as many people as possible.
I do have a small issue after converting things over. Sometimes when I try to close a database connection I get a PHP warning of:
PHP Warning: mysql_close(): 33 is not a valid MySQL-Link resource in /path/to/script.php on line #
and the line refers to the code below:
function DBclose($c){
if (isset($c) && !mysql_close($c)){
error_log("DB handle is invalid/null. Called from ".debug_backtrace()[2]['function'].'->'.debug_backtrace()[1]['function']);
}
}
This only happens sometimes.
What I want to do is change only this warning so that it includes the function that called it. Maybe to something more like:
PHP Warning: mysql_close(): 33 is not a valid MySQL-Link resource in /path/to/script.php on line # called from parent function <function-name>
How do I fix this and still make it so that other function calls I make that begin with # will have no errors printed on screen?
I don't think you can change the message, however, you can check if it's a resource using is_resource()

PHP - Parse ini file and access single values

In Python you can parse an .ini file and access the single values like this:
myini.ini
[STRINGS]
mystring = fooooo
value = foo_bar
script.py
import configparser
config = configparser.ConfigParser()
# ----------------------------------------------------------------------
config.read("myini.ini")
test = config["STRINGS"]["mystring"]
print (test) #-> OUTPUT: fooooo
How can I do the same in PHP? Unfortunately, I was not able to find any examples.
Not to fear, parsing an .ini file is a standard method. (See parse_ini_file in the php docs).
Using your file as the base of this example:
myini.ini
[STRINGS]
mystring = fooooo
value = foo_bar
test.php
$ini_array = parse_ini_file("myini.ini");
print_r($ini_array); # prints the entire parsed .ini file
print($ini_array['mystring']); #prints "fooooo"
Note that by default parse_ini_file ignores sections and gloms all ini settings into the same object. If you'd like to have things scoped sectionally as in your python example, pass true for the process_sections parameter (second parameter).
test2.php
$ini_array = parse_ini_file("myini.ini", true /* will scope sectionally */);
print($ini_array['mystring']); #prints nothing
print($ini_array['STRINGS']['mystring']); #prints fooooo
From the intermediate approach, to get match section, it needs to read any INI file from line to line, in this case you can use fgets function or stream_get_line function to read for each line until the section founded or end of file (not founded).
Inside every line we can use preg_match (using regex pattern) that match with the actual section name been searched.
The essential of this approach is to reduce memory usage meanwhile many concurrent request occurs at the same time, so in this case we use string object with any sufficient length as a buffer.
Good luck Buddy.

How to read a PHP file as text file to an array?

Here is my situation.Supposing I have a PHP file named as:
myfunctions.php
Is it possible to read the contents of that PHP file (myfunctions.php) in another script using available PHP functions?
I'm using the following functions without success in reading this PHP file:
file_get_contents()
file()
It simply returned blank. One of the possible successful method was to read this PHP file as text file but I do not know how to do this..If someone has some other methods, please share. Ideally I want the output to be an array so the data I would like to obtain will be easily manipulated for use.
Thanks.
If I were you, I will change the extension on the "myfunctions.php" to "myfunctions.txt" and use the theses functions
file_get_contents()
file()
But I don't know if you are allow to change the name of the document.
file() - Reads entire file into an array
fgets() - Gets line from file pointer
fread() - Binary-safe file read
readfile() - Outputs a file
file_put_contents() - Write a string to a file
stream_get_contents() - Reads remainder of a stream into a string
stream_context_create() - Creates a stream context
You need fread. To put it into an array, you might look at explode

Categories