【问题标题】:How to validate that the total can have a margin difference of +- 1 cent如何验证总额可以有 +- 1 美分的保证金差异
【发布时间】:2022-08-02 19:50:27
【问题描述】:

我正在寻找一种允许加载 XML 文件的解决方案,其中名为 Total 的值允许高于或低于实际值 1 美分的差异,对于这个解决方案,我从 XML 中获取 Total 的值文件如下。

$xml = new SimpleXMlElement( $_FILES[\'XmlToUpload\'][\'tmp_name\'], 0, true );
$total = (float)$xml[\'Total\'];

为了详细解释我想要实现的目标,我将放置以下示例,当读取 XML 文件的 Total 节点时,这将作为以下 Total= \"9840.00\" 的值,加载 XML 文件时我想要允许的是它允许总计有大约 1 美分的差异,也就是说,即使 XML 文件的总计值为 Total=\"9839.99\"Total=\"9840.01\",它也允许加载文件。

XML 文件按如下方式加载:

$fileXML = $_FILES[\'XmlToUpload\'][\'name\'];
$pathXML = \"//LOCATION/XML/\";
    
$filepathXML = $pathXML.$fileXML;



if(move_uploaded_file( $_FILES[\'XmlToUpload\'][\'tmp_name\'], $pathXML . $fileXML)){

echo \'Success Upload File\'; 

}

我希望有人能给我一些关于如何进行此验证的指导。

更新 1:

我添加了一个简短且具有代表性的 XML 文件示例,其中需要验证的 Total 节点位于

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

更新 2:

我试图根据他们给我的答案之一对我的代码进行修改,但我不存在,这可能是我遇到的一些额外错误,我尝试添加两个新变量,一个添加到总计金额\"0.01\"另一个变量减去\"0.01\".

变量声明如下:

$totalMgS = $total + \"0.01\";
$totalMgI = $total - \"0.01\";

重要的是要明确我之前在问题开头提到的$total,我用它来读取XML文件。

基于其中一个响应,我在 XML 文件的加载部分创建了以下验证:

if($total <= $totalMgS && $total >= $totalMgI){
if(move_uploaded_file( $_FILES[\'XmlToUpload\'][\'tmp_name\'], $pathXML . $fileXML)){

echo \'Success Upload File\'; 

}
}else{
echo \"It doesn\'t fit!\";

当我测试一个 XML 文件时,$total 的差异为0.01,该文件未加载,并向我抛出It doesn\'t fit! 的消息。

我需要对验证进行任何更改吗?

  • 比“实际价值”多还是少一分钱?您是否希望允许整数的 0.01 范围内的任何值,或者该值是否需要在 XML 文件中某个已知值或不同值的 0.01 范围内?
  • 你可以编辑你的问题并添加一个简短的,有代表性的$xml 的样本?
  • @EMF 在要上传的 XML 文件中找到的实际值多 1 美分或 1 美分
  • @JackFleeting 我刚刚使用您请求的 XML 文件对我的问题进行了更新
  • @ user11804298根据您的回答,实际值将始终在实际值的一分之内,因为它们是完全相同的数字。如果 Total = 1500.47,则它在 1500.47 的 1 美分以内。

标签: php xml


【解决方案1】:

首先,您问题中的示例 xml 格式不正确,因为它不包含 cfdi 的命名空间声明。

假设在下面的示例中已更正,您可以使用 xpath 将 Total 值与您的限制进行比较,而不是做任何您需要做的事情:

#note the change to the first line
$xml = '<cfdi:Voucher xmlns:cfdi="http://www.sat.gob.mx/cfd/3" 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>
';
$doc = new SimpleXMLElement($xml);
#one way to handle the namespaces:
$target = $doc->xpath('//*[local-name()="Voucher"]/@Total')[0];

if ($target <= 9840.01 && $target >= 9839.99) {
  echo "It fits!";
} else {
  echo "It doesn't fit!";
};

【讨论】:

  • 我很欣赏你的回答,但我认为我解释得不够清楚,我会再次解释,在添加总数的示例中定义为 9840.00,但并不总是总数会是这个值,我会加载不同的具有不同总数的 XML 文件。
  • @user11804298 是的,这只是一个示例,基于您的示例 xml。基本概念是您从Total 中提取值并将提取的值与您需要与之进行比较的任何内容进行比较(可能是在其他地方定义的两个变量) - 在本例中,高于或低于该值 0.01。
  • 我看到您已经将它与静态值进行比较,重要的是要记住我将加载不同的 XML 文件,这些文件将包含不同的值
  • @user11804298 仅在此示例中是静态的。在现实生活中,您可能会从某个地方加载这两个值,然后将提取的 Total 值与它们进行比较。
  • 我仍然不知道你的例子,这对我来说有点难以理解,因为那个验证,考虑到 Total 值会在我要加载的不同 XML 文件中发生变化,你可以给我一个例子根据我的问题,看看我是否能更多地理解你想要暗示的东西,我无限感谢你
【解决方案2】:

浮点数不适用于精度很重要的商业计算。使用浮点值的计算通常会带来不准确性。例子:

$diff = "9840.01" - "9840.00";
var_dump($diff);  //float(0.010000000000218)
var_dump($diff > 0.01);  //bool(true)

与默认值的差值正好是 1 美分。浮动比较会显示差异超过 1 美分。原因我就不细说了,网上有成千上万的帖子(Why not use Double or Float to represent currency?

一种可能的解决方案是使用BCMath(任意精度数学)。

function isDiffGt1Cent(string $actual, string $ref): bool
{
  $diff = bcsub($actual,$ref,3);
  return bccomp($diff,"0.01",3) === 1 OR bccomp($diff,"-0.01",3) === -1;
}

$d0 = isDiffGt1Cent("9840.00","9840.00");  // bool(false)
$d1 = isDiffGt1Cent("9840.01","9840.00");  // bool(false)
$d2 = isDiffGt1Cent("9839.99","9840.00");  // bool(false)
$d3 = isDiffGt1Cent("9840.02","9840.00");  // bool(true)
$d4 = isDiffGt1Cent("9839.98","9840.00");  // bool(true)

【讨论】:

  • 感谢您的回答,您可以根据问题代码添加一个示例,以便您可以利用它并为您的答案提供有效性
【解决方案3】:

而不是使用浮点数并比较到小数点后 2 位。 您可以做的是将 $total 变量乘以 100 并在 +-1 范围内进行比较,如下所示:

$xml = new SimpleXMlElement( $_FILES['XmlToUpload']['tmp_name'], 0, true );
$total = (float)$xml['Total'];
$newtotal = $total*100;
$totalMgS = $newtotal + 1;
$totalMgI = $newtotal - 1;

if($newtotal<= $totalMgS && $newtotal>= $totalMgI){
   if(move_uploaded_file( $_FILES['XmlToUpload']['tmp_name'], $pathXML . $fileXML)){
      echo 'Success Upload File'; 
   }
}else{
   echo "It doesn't fit!";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-24
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多