繁体   English   中英

如何读取 XML 文件并使用表中的数据进行验证

[英]How to read an XML file and validate with the data from a table

我正在创建一个允许加载 XML 文件的功能,但在加载它们之前我需要验证它们的内容,我不知道这是否是正确的方法,但我正在考虑首先阅读 XML 以查看其内容和然后用我存储在数据库表中的数据验证它。

目前我开发的是使用 AJAX 和 PHP 加载 XML 文件,如下所示。

这是我加载 XML 文件的表单的一部分

 <form action="" enctype="multipart/form-data"> <div class="form-group row"> <label for="fileToUpload" class="col-sm-3 col-form-label"> File XML:</label> <div class="col-sm-8"> <input type="file" name="fileToUpload" id="XmlToUpload" class="btn" accept=".xml" required> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button> <button type="button" id="upload" class="btn btn-success">Upload Documents</button> </div> </form>

以下是我加载文档并验证其格式的 JQuery function

$(document).ready(function(){
    $("#upload").on("click", function(){
        const ArchivoXml = $("#XmlToUpload").prop('files')[0];          

        
        if (ArchivoXml.type !== 'text/xml') {
            $('#XmlToUpload').val('');
            //$('#pdfToUpload').val('');
            alert('Please select the files with the correct format');
            return;
          }

        const datosForm = new FormData;

        datosForm.append("XmlToUpload", ArchivoXml);
       
        const filePath="server.php"
        //console.log(ArchivoXml);
        $.ajax({
            type:'POST',
            cache: false,
            contentType: false,
            processData: false,
            data: datosForm,
            url:filePath
        }).done(function(data){
            alert(data)
        }).fail(function(){
            alert('The file could not be loaded')
        });       
    });   
});

以下是 PHP 代码,我用它来指示它将存储的路径

server.php

<?php
    if(isset($_FILES["XmlToUpload"])){
        $archivo = $_FILES["XmlToUpload"]["name"];
        $ruta ="XML/";

        if(move_uploaded_file($_FILES["XmlToUpload"]["tmp_name"],$ruta.$archivo)){
            echo "Successfully uploaded";
        }else{
            echo "Error";
        }          
    }else {
        echo "A file was not selected";
    }
?>

正如我在问题开头提到的,我需要验证 XML 的内容,并使用数据库表中的信息进行验证。

XML 文件的结构将包含以下信息:

<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Voucher Version="3.3" Total="45264.13">
    <cfdi:Issuer Rfc="ABC123456AB1" Name="JOHN DOE"/>
     <cfdi:Concepts>
         <cfdi:Concept UnitValue="93.80">
        </cfdi:Concept>
    </cfdi:Concepts>
     <cfdi:Plugin>
        <tfd:Digital Version="1.1" />
    </cfdi:Plugin>
</cfdi:Voucher>

这里我有兴趣验证的数据是Total="45264.13"Rfc="ABC123456AB1"

除此之外,我开始了在 SQLServer 中创建存储过程的任务,以从数据库中获取信息,从而与 XML 数据和数据库中表的字段值进行比较。

USE [dbtest]
GO
/****** Object:  StoredProcedure [dbo].[sptest]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sptest]
    
AS
BEGIN
    
    Select VTB.RFC as 'RFC',
           LRC.QTY as 'QTY',  
           PL.PRICE as 'Price',
           (PL.PRICE *LRC.QTY) * 1.16 as 'Total'
    from PACKING RC  
        inner join VTABLE VTB on VTB.COLUMN = RC.INVOICE
        inner join TRANS LRC on (LRC.PACKING = RC.RECID)
        inner join PURCH PL on (PL.NUMBER =LRC.NUM and PL.PURCH =RC.PURCH)      
END

我希望有人可以指导我使用我正在创建的这个功能。

更新:

为了提供更快的验证,以便数据等于 XML 的内容,现在我决定在前面获取它们,也就是说,在我加载 XML 的相同视图中显示它们,如下所示:

 <div class="form-group row"> <label for="lblNombreVisita" class="col-sm-3 col-form-label">RFC:</label> <div class="col-sm-8"> <input type="text" class="form-control" id="txtRfc" disabled> </div> </div> <div class="form-group row"> <label for="lblNombreVisita" class="col-sm-3 col-form-label">Total:</label> <div class="col-sm-8"> <input type="text" class="form-control" id="txtTotal" disabled> </div> </div> <form action="" enctype="multipart/form-data"> <div class="form-group row"> <label for="fileToUpload" class="col-sm-3 col-form-label"> Archivo XML:</label> <div class="col-sm-8"> <input type="file" name="fileToUpload" id="XmlToUpload" class="btn" accept=".xml" required> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancelar</button> <button type="button" id="upload" class="btn btn-success">Subir Documentos</button> </div> </form>

同样,如果有人发现如何验证它们是否等于数据库中的值,它也是有效的,或者如果它们可以直接使用我在刚刚添加的文本字段中获得的值进行验证,它也是有效的。

假设您共享的 XML 是传递给 SQL 服务器的实际 XML,您将遇到命名空间的挑战。 它们需要在 XML 中声明,然后在查询数据时再次声明。

这是一个示例,它返回您共享的TotalRfc的值。

-- String holding the supplied XML.

DECLARE @my_xml varchar(MAX) = 
'<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Voucher Version="3.3" Total="45264.13">
  <cfdi:Issuer Rfc="ABC123456AB1" Name="JOHN DOE"/>
  <cfdi:Concepts>
    <cfdi:Concept UnitValue="93.80"></cfdi:Concept>
  </cfdi:Concepts>
  <cfdi:Plugin>
    <tfd:Digital Version="1.1" />
  </cfdi:Plugin>
</cfdi:Voucher>';

-- Remove the XML declaration and add the required namespaces via a "root" wrapper.
-- Note: You could use STUFF to place root after the declaration and keep it, but this was faster.

SELECT 
    @my_xml = REPLACE ( @my_xml, '<?xml version="1.0" encoding="UTF-8"?>', '' ),
    @my_xml = CONCAT ( '<root xmlns:cfdi="uri" xmlns:tfd="uri">', @my_xml, '</root>' );

-- Return the values for Total and Rfc.

SELECT
    t.c.value('declare namespace cfdi="uri"; (@Total)[1]', 'decimal(18,2)') AS Total,
    t.c.value('declare namespace cfdi="uri"; (cfdi:Issuer/@Rfc)[1]', 'varchar(50)') AS Rfc
FROM ( SELECT CAST ( @my_xml AS xml ) AS xml_data ) AS x
CROSS APPLY x.xml_data.nodes( 'declare namespace cfdi="uri"; //root/cfdi:Voucher' ) t(c);

退货

+----------+--------------+
|  Total   |     Rfc      |
+----------+--------------+
| 45264.13 | ABC123456AB1 |
+----------+--------------+

假设我了解您的验证和要求,您可以调整您的存储过程以接受您的 XML 作为参数,然后相应地进行验证/处理。

这是一个供参考的示例:

CREATE OR ALTER PROCEDURE [dbo].[sptest] (
    @my_xml varchar(MAX)   
)
AS
BEGIN
    
    DECLARE
        @rfc varchar(50), @qty int, @price decimal(18,2), @total decimal(18,2);

    /*****************************************/
    /*      Fetch values for validation      */
    /*****************************************/

    SELECT
        @rfc = VTB.RFC AS 'RFC',
        @qty = LRC.QTY AS 'QTY',  
        @price = PL.PRICE AS 'Price',
        @total = (PL.PRICE * LRC.QTY) * 1.16 AS 'Total'
    FROM PACKING AS RC  
    INNER JOIN VTABLE AS VTB 
        ON VTB.COLUMN = RC.INVOICE
    INNER JOIN TRANS AS LRC 
        ON (LRC.PACKING = RC.RECID)
    INNER JOIN PURCH AS PL 
        ON (PL.NUMBER =LRC.NUM and PL.PURCH =RC.PURCH)      

    /*****************************************/
    /*     Fetch XML values to validate      */
    /*****************************************/

    DECLARE
        @x_rfc varchar(50), @x_total decimal(18,2);

    -- Remove the XML declaration and add the required namespaces via a "root" wrapper.
    -- Note: You could use STUFF to place root after the declaration and keep it, but this was faster.

    SELECT 
        @my_xml = REPLACE ( @my_xml, '<?xml version="1.0" encoding="UTF-8"?>', '' ),
        @my_xml = CONCAT ( '<root xmlns:cfdi="uri" xmlns:tfd="uri">', @my_xml, '</root>' );

    -- Return the values for Total and Rfc.

    SELECT
        @x_total = t.c.value('declare namespace cfdi="uri"; (@Total)[1]', 'decimal(18,2)'),
        @x_rfc = t.c.value('declare namespace cfdi="uri"; (cfdi:Issuer/@Rfc)[1]', 'varchar(50)')
    FROM ( SELECT CAST ( @my_xml AS xml ) AS xml_data ) AS x
    CROSS APPLY x.xml_data.nodes( 'declare namespace cfdi="uri"; //root/cfdi:Voucher' ) t(c);

    /*****************************************/
    /*        Validate and handle XML        */
    /*****************************************/

    IF @rfc = @x_rfc AND @total = @x_total BEGIN

        -- Validation Success --
        -- Insert your XML to database...

    END ELSE BEGIN

        -- Validation Failure --
        -- Throw and error or whatever you need...

    END

END
GO

我在这里做了很多假设(比如你的 XML 和 SELECT 都只包含一条记录),但它应该让你前进。

由于您想首先使用存储在数据库中的数据验证 xml 数据,因此不要将 xml 文件移动到永久位置,我建议您阅读该文件并获取您想要验证的必填字段的值。 To get the values from xml file, You'll have to use any PHP provided XML library like DOMDocument , XMLReader , SimpleXML or you can use this XML2Array to convert xml to an associative array to easily get the value

if (isset($_FILES["XmlToUpload"])) {
    // Create a unique filename
    $fileName = $_FILES["XmlToUpload"]["name"];
    $ext = pathinfo($fileName, PATHINFO_EXTENSION);
    $archivo = uniqid($fileName, true);
    $ruta ="XML/";
    
    $xmlData = file_get_contents($_FILES['XmlToUpload']['tmp_name']);
        
    $arr = XML2Array::createArray($xmlData);
    
    //Check whether this array contains the required keys or not i.e. Total & Rfc
    if (! isset($arr['cfdi:Voucher']['@attributes']['Total'])) {
        echo "Error";
        exit();
    }
    $totalAmount = $arr['cfdi:Voucher']['@attributes']['Total'];
    
    if (! isset($arr['cfdi:Voucher']['cfdi:Issuer']['@attributes']['Rfc'])) {
        echo "Error";
        exit();
    }
    $rfc = $arr['cfdi:Voucher']['cfdi:Issuer']['@attributes']['Rfc'];
    
    // Validating $totalAmount & $rfc with the data in database
    // Connect to database (Sql Server)
    $serverName = "serverName\\sqlexpress";
    $connectionInfo = array( "Database"=>"dbName", "UID"=>"userName", "PWD"=>"password");
    $conn = sqlsrv_connect( $serverName, $connectionInfo);
    
    if ($conn === false) {
        die( print_r( sqlsrv_errors(), true));
    }
    
    $sql = "Select VTB.RFC as 'RFC',
            LRC.QTY as 'QTY',  
            PL.PRICE as 'Price',
            (PL.PRICE *LRC.QTY) * 1.16 as 'Total'
        from PACKING RC  
            inner join VTABLE VTB on VTB.COLUMN = RC.INVOICE
            inner join TRANS LRC on (LRC.PACKING = RC.RECID)
            inner join PURCH PL on (PL.NUMBER =LRC.NUM and PL.PURCH =RC.PURCH)   
        where VTB.RFC = ? AND ((PL.PRICE * LRC.QTY) * 1.16) = ?";
    
    $params = array($rfc, $totalAmount);
    $options =  array( "Scrollable" => SQLSRV_CURSOR_KEYSET );
    $stmt = sqlsrv_query( $conn, $sql, $params, $options);
    $row_count = sqlsrv_num_rows( $stmt );
    
    if ($row_count === false) {
        echo "Error";
    } else {
        if(move_uploaded_file($_FILES["XmlToUpload"]["tmp_name"],$ruta.$archivo)){
            echo "Successfully uploaded";
        }else{
            echo "Error";
        }
    }  
} else {
    echo "A file was not selected";
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM