SQL Server XML Parsing with CROSS APPLY

j7dteeu8  于 2023-10-15  发布在  其他
关注(0)|答案(2)|浏览(102)

I have been working on this XML, which is nested in a column of a table in SQL Server.

I have a code that worked for me until a few days ago, the problem I currently have that I have not been able to solve, which is why I have seen the need to post for help is the following.

The following code:

WITH XMLNAMESPACES('http://www.sat.gob.mx/cfd/4' AS cfdi, 
                    'http://www.sat.gob.mx/Pagos20' AS pago20, 
                    'http://www.sat.gob.mx/TimbreFiscalDigital' AS tfd)
  SELECT
      prx3_3.*
  FROM
(
 SELECT
    UUID,
    UUIDRelaciona = pd.value('@UUID', 'NVARCHAR(64)'),
    c.value('(@Total)', 'DECIMAL(26, 8)') AS TotalEgresos,
    x.value('(@Base)', 'DECIMAL(26,8)') AS Base,
    x.value('(@Importe)', 'DECIMAL(16,4)') AS ImporteTraslados
FROM [dbo].[XML]

    --El casteo ocurre aqui
    CROSS APPLY(SELECT CAST(XML AS XML)) A(TheXml)

    --Se llama a la funcion .nodes para retornar la tabla derivada de la consulta
    CROSS APPLY TheXml.nodes('/cfdi:Comprobante/cfdi:CfdiRelacionados/cfdi:CfdiRelacionado') AS i(pd)
    CROSS APPLY TheXml.nodes('/cfdi:Comprobante') AS C(c)
    CROSS APPLY TheXml.nodes('/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/cfdi:Impuestos/cfdi:Traslados/cfdi:Traslado') B(x) 
) prx3_3

This is my XML:

<?xml version="1.0" encoding="iso-8859-1"?>
    <cfdi:Comprobante xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd" xmlns:cfdi="http://www.sat.gob.mx/cfd/4" Version="4.0" Serie="NC" Folio="1500" Fecha="2023-06-06T14:58:38" Sello="FKE==" FormaPago="99" NoCertificado="00001000000504344657" Certificado="MIIF4=" SubTotal="9006.47" Moneda="MXN" Total="10447.51" TipoDeComprobante="E" Exportacion="01" MetodoPago="PUE" LugarExpedicion="52160">
        <cfdi:CfdiRelacionados TipoRelacion="01">
            <cfdi:CfdiRelacionado UUID="8D6A947B-55D5-7F47-9541-4DFEDFADFD76" />
            <cfdi:CfdiRelacionado UUID="22F27E3B-938F-A747-873F-CB12D8C3D618" />
            <cfdi:CfdiRelacionado UUID="02FC251C-D156-0F4D-B9D6-0FD3A099CD0E" />
            <cfdi:CfdiRelacionado UUID="36FAACBA-6134-2640-AEB0-07F2C3913E94" />
            <cfdi:CfdiRelacionado UUID="016E4B16-2A41-1746-B5A1-FD34722965F6" />
        </cfdi:CfdiRelacionados>
        <cfdi:Emisor Rfc="CVE160307HY1" Nombre="CADENA 24" RegimenFiscal="601" />
        <cfdi:Receptor Rfc="SON990511MI0" Nombre="SONIGAS" DomicilioFiscalReceptor="37500" RegimenFiscalReceptor="601" UsoCFDI="G02" />
        <cfdi:Conceptos>
            <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT" Descripcion="Nota de crédito de Interés moratorio 22314 01/feb./2023" ValorUnitario="320.16" Importe="320.16" ObjetoImp="02">
                <cfdi:Impuestos>
                    <cfdi:Traslados>
                    <cfdi:Traslado Base="320.16" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="51.23" />
                    </cfdi:Traslados>
                </cfdi:Impuestos>
            </cfdi:Concepto>
            <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT" Descripcion="Nota de crédito de Interés moratorio 22988 01/mar./2023" ValorUnitario="1723.86" Importe="1723.86" ObjetoImp="02">
                <cfdi:Impuestos>
                    <cfdi:Traslados>
                        <cfdi:Traslado Base="1723.86" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="275.82" />
                    </cfdi:Traslados>
                </cfdi:Impuestos>
            </cfdi:Concepto>
            <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT" Descripcion="Nota de crédito de Interés moratorio 25094 11/abr./2023" ValorUnitario="1794.99" Importe="1794.99" ObjetoImp="02">
                <cfdi:Impuestos>
                    <cfdi:Traslados>
                        <cfdi:Traslado Base="1794.99" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="287.20" />
                    </cfdi:Traslados>
                </cfdi:Impuestos>
            </cfdi:Concepto>
            <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT" Descripcion="Nota de crédito de Interés moratorio 25773 01/may./2023" ValorUnitario="3198.69" Importe="3198.69" ObjetoImp="02">
                <cfdi:Impuestos>
                    <cfdi:Traslados>
                        <cfdi:Traslado Base="3198.69" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="511.79" />
                    </cfdi:Traslados>
                </cfdi:Impuestos>
            </cfdi:Concepto>
            <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT" Descripcion="Nota de crédito de Interés moratorio 26356 01/jun./2023" ValorUnitario="1968.77" Importe="1968.77" ObjetoImp="02">
                <cfdi:Impuestos>
                    <cfdi:Traslados>
                        <cfdi:Traslado Base="1968.77" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="315.00" />
                    </cfdi:Traslados>
                </cfdi:Impuestos>
            </cfdi:Concepto>
        </cfdi:Conceptos>
        <cfdi:Impuestos TotalImpuestosTrasladados="1441.04">
            <cfdi:Traslados>
                <cfdi:Traslado Base="9006.47" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="1441.04" />
            </cfdi:Traslados>
        </cfdi:Impuestos>
        <cfdi:Complemento>
            <tfd:TimbreFiscalDigital xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/cfd/TimbreFiscalDigital/TimbreFiscalDigitalv11.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="1.1" UUID="126F9C73-DD92-2943-AA07-320EB2955100" FechaTimbrado="2023-06-06T15:00:30" RfcProvCertif="SCD110105654" SelloCFD="FKEz==" NoCertificadoSAT="00001000000502000436" SelloSAT="XLREB==" />
        </cfdi:Complemento>
    </cfdi:Comprobante>

The result I hope for is the following table:

UUIDUUIDRelacionaTotalEgresosBaseImporteTraslado
126F9C73-DD92-2943-AA07-320EB29551008D6A947B-55D5-7F47-9541-4DFEDFADFD7610447.51320.1751.23
126F9C73-DD92-2943-AA07-320EB295510022F27E3B-938F-A747-873F-CB12D8C3D61810447.511723.86275.82
126F9C73-DD92-2943-AA07-320EB295510002FC251C-D156-0F4D-B9D6-0FD3A099CD0E10447.511794.99287.20
126F9C73-DD92-2943-AA07-320EB295510036FAACBA-6134-2640-AEB0-07F2C3913E9410447.513198.69315.00
8hhllhi2

8hhllhi21#

Please try the following solution.

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (UUID UNIQUEIDENTIFIER PRIMARY KEY, xmldata NVARCHAR(MAX));
INSERT @tbl (UUID, xmldata) VALUES
('126F9C73-DD92-2943-AA07-320EB2955100', N'<cfdi:Comprobante xmlns:cfdi="sat.gob.mx/cfd/4"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd"
                  MetodoPago="PUE" LugarExpedicion="52160" Total="10447.51">
    <cfdi:CfdiRelacionados TipoRelacion="01">
        <cfdi:CfdiRelacionado UUID="8D6A947B-55D5-7F47-9541-4DFEDFADFD76"/>
        <cfdi:CfdiRelacionado UUID="22F27E3B-938F-A747-873F-CB12D8C3D618"/>
        <cfdi:CfdiRelacionado UUID="02FC251C-D156-0F4D-B9D6-0FD3A099CD0E"/>
        <cfdi:CfdiRelacionado UUID="36FAACBA-6134-2640-AEB0-07F2C3913E94"/>
        <cfdi:CfdiRelacionado UUID="016E4B16-2A41-1746-B5A1-FD34722965F6"/>
    </cfdi:CfdiRelacionados>
    <cfdi:Emisor Rfc="CVE160307HY1" Nombre="CADENA 24" RegimenFiscal="601"/>
    <cfdi:Receptor Rfc="SON990511MI0" Nombre="SONIGAS"
                   DomicilioFiscalReceptor="37500" RegimenFiscalReceptor="601"
                   UsoCFDI="G02"/>
    <cfdi:Conceptos>
        <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT"
                       Descripcion="Nota de crédito de Interés moratorio 22314 01/feb./2023"
                       ValorUnitario="320.16" Importe="320.16" ObjetoImp="02">
            <cfdi:Impuestos>
                <cfdi:Traslados>
                    <cfdi:Traslado Base="320.16" Impuesto="002"
                                   TipoFactor="Tasa" TasaOCuota="0.160000"
                                   Importe="51.23"/>
                </cfdi:Traslados>
            </cfdi:Impuestos>
        </cfdi:Concepto>
        <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT"
                       Descripcion="Nota de crédito de Interés moratorio 22988 01/mar./2023"
                       ValorUnitario="1723.86" Importe="1723.86" ObjetoImp="02">
            <cfdi:Impuestos>
                <cfdi:Traslados>
                    <cfdi:Traslado Base="1723.86" Impuesto="002"
                                   TipoFactor="Tasa" TasaOCuota="0.160000"
                                   Importe="275.82"/>
                </cfdi:Traslados>
            </cfdi:Impuestos>
        </cfdi:Concepto>
        <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT"
                       Descripcion="Nota de crédito de Interés moratorio 25094 11/abr./2023"
                       ValorUnitario="1794.99" Importe="1794.99" ObjetoImp="02">
            <cfdi:Impuestos>
                <cfdi:Traslados>
                    <cfdi:Traslado Base="1794.99" Impuesto="002"
                                   TipoFactor="Tasa" TasaOCuota="0.160000"
                                   Importe="287.20"/>
                </cfdi:Traslados>
            </cfdi:Impuestos>
        </cfdi:Concepto>
        <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT"
                       Descripcion="Nota de crédito de Interés moratorio 25773 01/may./2023"
                       ValorUnitario="3198.69" Importe="3198.69" ObjetoImp="02">
            <cfdi:Impuestos>
                <cfdi:Traslados>
                    <cfdi:Traslado Base="3198.69" Impuesto="002"
                                   TipoFactor="Tasa" TasaOCuota="0.160000"
                                   Importe="511.79"/>
                </cfdi:Traslados>
            </cfdi:Impuestos>
        </cfdi:Concepto>
        <cfdi:Concepto ClaveProdServ="84111506" Cantidad="1" ClaveUnidad="ACT"
                       Descripcion="Nota de crédito de Interés moratorio 26356 01/jun./2023"
                       ValorUnitario="1968.77" Importe="1968.77" ObjetoImp="02">
            <cfdi:Impuestos>
                <cfdi:Traslados>
                    <cfdi:Traslado Base="1968.77" Impuesto="002"
                                   TipoFactor="Tasa" TasaOCuota="0.160000"
                                   Importe="315.00"/>
                </cfdi:Traslados>
            </cfdi:Impuestos>
        </cfdi:Concepto>
    </cfdi:Conceptos>
    <cfdi:Impuestos TotalImpuestosTrasladados="1441.04">
        <cfdi:Traslados>
            <cfdi:Traslado Base="9006.47" Impuesto="002" TipoFactor="Tasa"
                           TasaOCuota="0.160000" Importe="1441.04"/>
        </cfdi:Traslados>
    </cfdi:Impuestos>
</cfdi:Comprobante>');
-- DDL and sample data population, end

WITH XMLNAMESPACES(DEFAULT 'sat.gob.mx/cfd/4')
SELECT t.UUID
    , x.value('@UUID', 'UNIQUEIDENTIFIER') AS UUIDRelaciona
    , x.value('(/Comprobante/@Total)[1]', 'DECIMAL(10,2)') AS TotalEgresos
    --, seq.pos
    , c.value('@Base', 'DECIMAL(10,2)') AS Base
    , c.value('@Importe', 'DECIMAL(10,2)') AS ImporteTraslado
FROM @tbl AS t
CROSS APPLY (SELECT CAST(xmldata AS XML)) t1(TheXml)
CROSS APPLY TheXml.nodes('/Comprobante/CfdiRelacionados/CfdiRelacionado') t2(x)
CROSS APPLY (SELECT t2.x.value('let $n := . return count(../*[. << $n[1]]) + 1','INT') AS pos
         ) AS seq
CROSS APPLY TheXml.nodes('/Comprobante/Conceptos/Concepto[sql:column("seq.pos")]/Impuestos/Traslados/Traslado') AS t3(c);

Output

UUIDUUIDRelacionaTotalEgresosBaseImporteTraslado
126F9C73-DD92-2943-AA07-320EB29551008D6A947B-55D5-7F47-9541-4DFEDFADFD7610447.51320.1651.23
126F9C73-DD92-2943-AA07-320EB295510022F27E3B-938F-A747-873F-CB12D8C3D61810447.511723.86275.82
126F9C73-DD92-2943-AA07-320EB295510002FC251C-D156-0F4D-B9D6-0FD3A099CD0E10447.511794.99287.20
126F9C73-DD92-2943-AA07-320EB295510036FAACBA-6134-2640-AEB0-07F2C3913E9410447.513198.69511.79
126F9C73-DD92-2943-AA07-320EB2955100016E4B16-2A41-1746-B5A1-FD34722965F610447.511968.77315.00
gpnt7bae

gpnt7bae2#

You need to work out the positions of the UUID values in order to correlate them to the rest of the XML.

Unfortunately SQL Server does not support the position(.) function, but you can hack it by counting the previous nodes.

Then you need to pass that value into an XQuery predicate using sql:column

WITH XMLNAMESPACES(
  DEFAULT 'sat.gob.mx/cfd/4'
)
SELECT
    UUID,
    v.UUIDRelaciona,
    Comprobante.value('(@Total)', 'DECIMAL(26, 8)') AS TotalEgresos,
    x.value('(@Base)', 'DECIMAL(26,8)') AS Base,
    x.value('(@Importe)', 'DECIMAL(16,4)') AS ImporteTraslados
FROM [dbo].[XML]
    --El casteo ocurre aqui
CROSS APPLY(SELECT CAST(XML AS XML)) A(TheXml)

    --Se llama a la funcion .nodes para retornar la tabla derivada de la consulta
CROSS APPLY TheXml.nodes('/Comprobante') x1(Comprobante)
CROSS APPLY Comprobante.nodes('CfdiRelacionados/CfdiRelacionado') AS i(pd)
CROSS APPLY (
    SELECT
      UUIDRelaciona = pd.value('@UUID', 'uniqueidentifier'),
      pos = pd.value('let $i := . return count(../CfdiRelacionado[. << $i]) + 1', 'int')
) v
CROSS APPLY Comprobante.nodes('Conceptos/Concepto[sql:column("v.pos")]/Impuestos/Traslados/Traslado') B(x)

db<>fiddle

Note also the use of a DEFAULT namespace to make it more readable.

相关问题