I am looking for a solution to allow the loading of an XML file where the named value Total
allows a difference of 1 cent above or below the actual value, for this solution I get the value of the Total XML file as follows:
$xml = new SimpleXMlElement( $_FILES['XmlToUpload']['tmp_name'], 0, true );
$total = (float)$xml['Total'];
To explain in detail what I want to achieve I will put the following example, when reading the node Total
of the XML file it obtains the following value Total= "9840.00"
, what I want to allow when loading the XML file is that it allows that total even if it has a difference of more or less 1 cent, that is, even if the Total
XML file has a value of Total="9839.99"
o Total="9840.01"
allows the file to be loaded.
The XML file is loaded as follows:
$fileXML = $_FILES['XmlToUpload']['name'];
$pathXML = "//LOCATION/XML/";
$filepathXML = $pathXML.$fileXML;
if(move_uploaded_file( $_FILES['XmlToUpload']['tmp_name'], $pathXML . $fileXML)){
echo 'Success Upload File';
}
I hope someone can give me some guidance on how to do this validation.
Update 1:
What I tried to compare the Total value if it is within the 1-cent slack was to add two new variables, one adding to the total an amount of "0.01" and the other variable subtracting the amount of "0.01" .
I declare the variables as follows:
$totalMgS = $total + "0.01";
$totalMgI = $total - "0.01";
I then go ahead and create the following validation in the load section of my XML file:
if($total <= $totalMgS && $total >= $totalMgI){
if(move_uploaded_file( $_FILES['XmlToUpload']['tmp_name'], $pathXML . $fileXML)){
echo 'Esta dentro de la holgura';
}
}else{
echo "No esta dentro de la holgura";
}
When I try to load an XML file where $total
it has a difference of 0.01, the file does not load and it gives me the message "It is not within the slack"
Are there any changes I need to make to my validation?
Update 2
Returning to the topic again and to validate it, I was analyzing all this time that I have to compare the total with another, and indeed now I visualize it like this, that other number with which I have to compare it is stored in a database table which I am displaying in an HTML tag as follows:
<div class="form-group row" >
<label for="lblName" class="col-sm-3 col-form-label">Total:</label>
<div class="col-sm-8">
<input type="text" name="txtTotal" class="form-control" id="txtTotal" disabled>
</div>
</div>
Then I declare in my Javascript the variable:
var TotalTable = $("#txtTotal").val();
Then I add it to my data to later be called from PHP.
datosForm.append("TotalTable", $("#txTotal").val());
And finally I call it from PHP.
$TotalReal = (isset($_POST["TotalTable"]));
I have called my variable in PHP as$TotalReal
To validate that the total is the same that I have in my HTML tag and that it is the same that I have stored in the database, I print the variable $TotalReal
but this only returns 1.
I am printing it as follows:
echo $TotalReal;
Is there something I need to change in how I am getting the variable from Javascript? Or do I have to do some conversion to data type float
?
Update 3:
To assign the value to the input I do it from a Javascript function as follows:
function CargarArchivo (Total){
$("#txtTotal").val(Total);
}
Update 4:
I have adapted my code to an answer, but when trying to print the result of my variable isundefined
$totalreal = (isset($_POST['TotalTable']));
if(isset($_POST['TotalTable']) ) {
$totalreal = $_POST['TotalTable'];
} else {
// No se recibió ningún valor en el input 'TotalTable'
}
$margen = "0.01";
echo $totalreal;
if($total >= $totalreal - $margen && $total <= $totalreal + $margen){// Está dentro del margen
} else {
// No está dentro del margen
}
As you can see, I am printing before, just for testing purposes, the $totalreal
, but this returns a variableundefined
Update 5:
I have corrected the problem of the undefined variable, this was because the variable that I was placing in the data did not exist, this was because I needed a letter in the name of the variable, it is now corrected.
Now the problem that I am having is that the XML file that I am loading has the difference of 1 cent against $totalreal
it and even so the error that it indicates is that it is not within the margin.
For what it's worth, I add the XML file that I'm loading and which contains the node that I want to compare.
<cfdi:Voucher xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
Certificated="m4gfzi9yNXuC0A="
Condition="002"
Date="2021-06-29T16:02:16"
Number="4938"
Payment="23"
NoCertificated="404627114"
Total="9840.00"
Version="3.3">
</cfdi:Voucher>
It is important to make it clear that I am already reading that $total from the XML file as follows:
$total = (float)$xml['Total'];
Is there any modification that I need to do in the validation ?
Good day,
Note: To make the answer a little shorter, I am assuming that you have already fixed all the additional problems that you put in your question and you can read the value of both the
XML
and the value that will be the reference and the value of the margin (In case it is can configure from somewhere) and I'll focus directly on the validation part which is the original question.This is a common problem when comparing real numbers (and it occurs in any programming language).
Context
From the official documentation
php
we read the following excerpt:applied to your code
First you have to convert the numbers from
string
tofloat
, for that you can usefloatval()
. Simulating the value you load from itXML
with the variable$xml
:Then we are going to compare the values, the same documentation (I put the link above) shows a method to compare it that we are going to adapt:
Example from the documentation:
Adaptation to the generic example of this answer:
If we just run the program as-is we'll see that the answer is
"no carga"
despite the fact that the$total
y value$referencia
is apparently within the range we set (results may vary by operating system, as the documentation explains).If we add a line (It can be a simple
printf
) to know the value ofabs($total - $referencia)
we will see the following:Result:
All those extra decimal places come from the "limited precision" mentioned in the documentation, so the correct way to do it would be to round to limit the comparison to two decimal places.
Note: When rounding you can use
round()
,floor()
orceil()
at your convenience, please check the documentation to know the difference between these functions. For the example I will useround()
.Applying rounding to the code we have the following form:
Which returns:
To validate the margin of difference, as you were told in the comments, you need something to compare to.
That something I see in your code is the following line:
Which, as you say, returns a
1
. This is because you are assigning to$TotalReal
the return value of the isset function . And it returns true if the variable passed by argument exists. That variable exists, so it returns a boolean value that is then translated as 1 .Your code should look like this:
Once that's fixed now you could do the comparisons.
Assuming that the variable
$total
contains the total to compare and the variable$TotalReal
is the one with which you are going to measure the margin of difference: we are going to add one more variable that is going to be the margin:$margen = '0.01'
.Perhaps you need the value to compare to be defined with a name other than the reference name?