Lector XML para SQL implementado en sap

Hola buen día

Una consulta Expertos alguien tendrá o me podría ayudar a realizar una consulta o decirme el por donde empezar, tengo un código con el que estoy leyendo mi XML en practica aparentemente todo va bien el problema reside en la tabla de conceptos que cuando tengo dos líneas me lee únicamente uno el desarrollo se esta haciendo en sql ya que lo vi un poco mas factible

por ejemplo aqui tengo dos lineas en el nodo de conceptos

-<cfdi:Concepto Descuento=“0.00” Importe=“390.84” ValorUnitario=“195.42” Descripcion=“COMBI SALSA TAQUERA 24/210 G” ClaveUnidad=“XBX” Cantidad=“2.0000” NoIdentificacion=“00000075014452” ClaveProdServ=“50171800”>

-<cfdi:Concepto Descuento=“0.00” Importe=“586.26” ValorUnitario=“195.42” Descripcion=“COMBI SALSA VERDE 24/210 G” ClaveUnidad=“XBX” Cantidad=“3.0000” NoIdentificacion=“00000075014469” ClaveProdServ=“50171800”>

se supone que quiero leer de una 1 a ilimitadas lineas para extraer dicha informacion.

si alguien tiene alguna sugerencia del query a usar

Hola este es un SP que hice para extraer información de un XML, te la comparto porque hace algún tiempo estuve en tu lugar, solo extraigo cierta información y la ingreso a una tabla, después ya hago uso de ella.
Entiendo lo que quieres hacer, pero no entiendo porque esa información la quieres sacar del XML si ya esta en una tabla que es INV1.
En teoría debes leer toda la linea completa, ya que al momento de manejar los datos de XML en SQL se vuelve texto, tienes que separarlas mediante comando de SQL.
Intenta usar STRING_SPLIT
h_tps://www.sqlshack.com/es/la-funcion-string_split-en-sql-server/

USE [MiBASE]
GO
/****** Object:  StoredProcedure [dbo].[SIP_XMLimportXML]    Script Date: 03/12/2021 01:24:34 p. m. ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<kriptonniano>
-- Create date: <20-04-2021>
-- Description:	<Procedimiento para obtener información del xml de facturación>
-- =============================================
Create PROCEDURE [dbo].[SIP_XMLimportXML]
		@docentry as varchar(100)
		--@donum as varchar(100)
AS
BEGIN
	
	SET NOCOUNT ON;
DECLARE @Data as XML
DECLARE @xml as XML
DECLARE @ruta AS varchar(100)
DECLARE @RUTA2 AS varchar(200)
DECLARE @NoFol as varchar(200)
DECLARE @XML2 as varchar(1000)
DECLARE @sql as varchar(max)

SET @NoFol = (SELECT T0.ReportID FROM MiBASE.[dbo].ECM2 T0 WHERE  T0.[SrcObjType]=13 AND T0.[SrcObjAbs]=@docentry)
SET @RUTA2= (select convert(varchar(4),year(t0.DocDate))+'-' + RIGHT('00' + Ltrim(Rtrim(month(t0.DocDate))),2) +'\'+T0.CardCode+'\IN\'
from SBOSIP_ASC2.[dbo].OINV t0 WHERE t0.DocEntry=@docentry)

--Ruta del XML Generado
SET @Ruta = (select convert(varchar(249), XmlPath)+'0010000100\0010000100\'+@RUTA2 from MiBASE.[dbo].OADM)
SET @XML2  = (@Ruta +   @NoFol + '.xml')

DECLARE @SQL_BULK VARCHAR(MAX)

SELECT @sql = 'insert INTO SBO_SIP_XML_Open_XML (Data,DocEntry) SELECT *,'+@docentry+' FROM OPENROWSET (BULK '''+ @XML2+''', SINGLE_BLOB) AS data'
EXEC sp_sqlexec @sql
-- Tabla SBO_SIP_XML_Open_XML donde almaceno el texto del XML y el Docentry
SELECT @xml=Data FROM SBO_SIP_XML_Open_XML where docentry=@docentry
--SELECT @xml;
;WITH xmlnamespaces('http://www.sat.gob.mx/cfd/3' AS cfdi
        , 'http://www.w3.org/2001/XMLSchema-instance' AS xsi
        , 'http://www.sat.gob.mx/TimbreFiscalDigital' AS tfd
        , 'http://www.sat.gob.mx/TimbreFiscalDigital' AS schemaLocation)
-- Tabla SBO_SIP_Facturas que uso para guardar los datos que extraigo del XML 
--Campos que estoy insertando en la tabla [Folio], [FechaTimbrado], [NoCertificadoSAT], [SelloCFD], [SelloSAT], [UUID], [Version], [UsoCFDI], [Rfc] 

Insert into SBO_SIP_Facturas (Folio,FechaTimbrado,NoCertificadoSAT,SelloCFD,
SelloSAT,UUID,Version,UsoCFDI,Rfc) SELECT
Comprobante.value('@Folio','int')'Folio',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@FechaTimbrado)[1]','datetime')'FechaTimbrado',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@NoCertificadoSAT)[1]','nvarchar(MAX)')'NoCertificadoSAT',
Comprobante.value('@Sello','nvarchar(MAX)')'SelloCFD',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@SelloSAT)[1]','nvarchar(MAX)')'SelloSAT',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@UUID)[1]','nvarchar(MAX)')'UUID',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@Version)[1]','decimal(18, 1)')'Version',
Comprobante.value('(cfdi:Receptor/@UsoCFDI)[1]','nvarchar(MAX)')'UsoCFDI',
Comprobante.value('(cfdi:Emisor/@Rfc)[1]','nvarchar(MAX)') 'Rfc'
FROM @xml.nodes ('/cfdi:Comprobante') t1(Comprobante) 

	END
1 me gusta

Hola buenas Tardes Gracias por Interesarte en el Post

si de hecho si vi que subiste hace tiempo tu lector de xml, referente a tu consulta del porque quiero leer solo ese campo, estoy implementando el sistema no se si vivas en mexico es la famosa carta porte, entonces tengo el cliente que me envia dicho xml asi como lo mande en total por ejemplo son 2 o mas lineas de mercancias la idea que quiero es que ese lector me lea dicha informacion, el problema que me tome es en las lineas al querer hacer el update en una tabla que cree en sql solo que el update no logro que me lea las 2 lineas aparentemente solo me lee una linea.

es por eso la razon si tienes alguna otra informacion al respecto para generar dicho mapeo o alguna forma de como hacerlo te lo agradeceria.

saludos

Realice una prueba y cambiando solo el numero que esta entre [1] por el numero de campo que quieres te lo va a dar, por ejemplo tu caso para elegir el segundo tendrás que cambiar el por el 1 por el 2 algo así!

Insert into SBO_SIP_Facturas (Folio,FechaTimbrado,NoCertificadoSAT,SelloCFD,
SelloSAT,UUID,Version,UsoCFDI,Rfc,Importe, ValorUnitario,Descripcion,ClaveUnidad,Cantidad,ClaveProdServ) SELECT
Comprobante.value('@Folio','int')'Folio',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@FechaTimbrado)[1]','datetime')'FechaTimbrado',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@NoCertificadoSAT)[1]','nvarchar(MAX)')'NoCertificadoSAT',
Comprobante.value('@Sello','nvarchar(MAX)')'SelloCFD',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@SelloSAT)[1]','nvarchar(MAX)')'SelloSAT',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@UUID)[1]','nvarchar(MAX)')'UUID',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@Version)[1]','decimal(18, 1)')'Version',
Comprobante.value('(cfdi:Receptor/@UsoCFDI)[1]','nvarchar(MAX)')'UsoCFDI',
Comprobante.value('(cfdi:Emisor/@Rfc)[1]','nvarchar(MAX)') 'Rfc',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@Importe)[2]','nvarchar(MAX)') 'Importe',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ValorUnitario)[2]','nvarchar(MAX)') 'ValorUnitario',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@Descripcion)[2]','nvarchar(MAX)') 'Descripcion',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ClaveUnidad)[2]','nvarchar(MAX)') 'ClaveUnidad',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@Cantidad)[2]','nvarchar(MAX)') 'Cantidad',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ClaveProdServ)[2]','nvarchar(MAX)') 'ClaveProdServ'
FROM @xml.nodes ('/cfdi:Comprobante') t1(Comprobante) 

	END
- <cfdi:Conceptos>
- <cfdi:Concepto ClaveProdServ="78121600" Cantidad="1.000000" ClaveUnidad="E48" Descripcion="RECEPCION, RESGUARDO, ESTADIA Y TRANSVASE DE CARRO TANQUE" ValorUnitario="720.00" Importe="720.00">
- <cfdi:Impuestos>
+ <cfdi:Traslados>
  <cfdi:Traslado Base="720.00" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="115.20" /> 
  </cfdi:Traslados>
  </cfdi:Impuestos>
  </cfdi:Concepto>
- <cfdi:Concepto ClaveProdServ="78121600" Cantidad="3.000000" ClaveUnidad="E48" Descripcion="BASCULA PIPA" ValorUnitario="4.00" Importe="12.00">


Omite los NULL ya que estuve haciendo pruebas
Ya solo tendrías que agregar un ciclo para que realice la inserción hasta que llegue a 0 o null

o en caso contrario que no encuentres la forma de hacer el ciclo, solo cambiando el numero de corchetes y crear un SP que elimine los registros con Null. Me doy cuenta que si lo repites se insertan al mismo tiempo.

Insert into SBO_SIP_Facturas (Folio,FechaTimbrado,NoCertificadoSAT,SelloCFD,
SelloSAT,UUID,Version,UsoCFDI,Rfc,Importe, ValorUnitario,Descripcion,ClaveUnidad,Cantidad,ClaveProdServ) SELECT
Comprobante.value('@Folio','int')'Folio',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@FechaTimbrado)[1]','datetime')'FechaTimbrado',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@NoCertificadoSAT)[1]','nvarchar(MAX)')'NoCertificadoSAT',
Comprobante.value('@Sello','nvarchar(MAX)')'SelloCFD',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@SelloSAT)[1]','nvarchar(MAX)')'SelloSAT',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@UUID)[1]','nvarchar(MAX)')'UUID',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@Version)[1]','decimal(18, 1)')'Version',
Comprobante.value('(cfdi:Receptor/@UsoCFDI)[1]','nvarchar(MAX)')'UsoCFDI',
Comprobante.value('(cfdi:Emisor/@Rfc)[1]','nvarchar(MAX)') 'Rfc',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@Importe)[1]','nvarchar(MAX)') 'Importe',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ValorUnitario)[1]','nvarchar(MAX)') 'ValorUnitario',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@Descripcion)[1]','nvarchar(MAX)') 'Descripcion',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ClaveUnidad)[1]','nvarchar(MAX)') 'ClaveUnidad',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@Cantidad)[1]','nvarchar(MAX)') 'Cantidad',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ClaveProdServ)[1]','nvarchar(MAX)') 'ClaveProdServ'
FROM @xml.nodes ('/cfdi:Comprobante') t1(Comprobante) 
;WITH xmlnamespaces('http://www.sat.gob.mx/cfd/3' AS cfdi
        , 'http://www.w3.org/2001/XMLSchema-instance' AS xsi
        , 'http://www.sat.gob.mx/TimbreFiscalDigital' AS tfd
        , 'http://www.sat.gob.mx/TimbreFiscalDigital' AS schemaLocation)
Insert into SBO_SIP_Facturas (Folio,FechaTimbrado,NoCertificadoSAT,SelloCFD,
SelloSAT,UUID,Version,UsoCFDI,Rfc,Importe, ValorUnitario,Descripcion,ClaveUnidad,Cantidad,ClaveProdServ) SELECT
Comprobante.value('@Folio','int')'Folio',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@FechaTimbrado)[1]','datetime')'FechaTimbrado',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@NoCertificadoSAT)[1]','nvarchar(MAX)')'NoCertificadoSAT',
Comprobante.value('@Sello','nvarchar(MAX)')'SelloCFD',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@SelloSAT)[1]','nvarchar(MAX)')'SelloSAT',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@UUID)[1]','nvarchar(MAX)')'UUID',
Comprobante.value('(/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital/@Version)[1]','decimal(18, 1)')'Version',
Comprobante.value('(cfdi:Receptor/@UsoCFDI)[1]','nvarchar(MAX)')'UsoCFDI',
Comprobante.value('(cfdi:Emisor/@Rfc)[1]','nvarchar(MAX)') 'Rfc',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@Importe)[2]','nvarchar(MAX)') 'Importe',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ValorUnitario)[2]','nvarchar(MAX)') 'ValorUnitario',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@Descripcion)[2]','nvarchar(MAX)') 'Descripcion',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ClaveUnidad)[2]','nvarchar(MAX)') 'ClaveUnidad',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@Cantidad)[2]','nvarchar(MAX)') 'Cantidad',
Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ClaveProdServ)[2]','nvarchar(MAX)') 'ClaveProdServ'
FROM @xml.nodes ('/cfdi:Comprobante') t1(Comprobante) 
	END

Hola bro … una consulta enorme aparentemente si me sirvió pero aquí mismo como le puedo hacer para que me lea la información de otro nodo por ejemplo actualmente, me lee bien el XML solo que tengo el detalle cuando quiero leer un complemento en especifico esa parte ya no me la lee.

Supongamos esta es la estructura de tu XML
Y quieres obtener el valor de TotalImpuestosTrasladados en vez de ClaveProdServ
Solo hay que cambiar la variables:

Comprobante.value('(/cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/@ClaveProdServ)[2]','nvarchar(MAX)') 'ClaveProdServ'

Por esto:

Comprobante.value('(/cfdi:Comprobante/cfdi:Impuestos/@TotalImpuestosTrasladados)[1]','nvarchar(MAX)') 'ClaveProdServ'

En este ejemplo me obtendrá el valor de 4482.08

Hola buen dia Muchas Gracias por tu respuesta @kriptonniano

me ha estado funcionando la informacion que me haz proporcionado la verdad te agradezco demasiado que te hayas interesado en mi tema.

cualquier cosa cuenta conmigo para cualquier ayuda hermano

1 me gusta

Por fa, marca la respuesta del colega que más te haya ayudado así el tema queda “solucionado” :pray:

1 me gusta

Hola buen dia Amigo SidV

ya marque la solucion muchas gracias a @kriptonniano por ayudarme en el tema

saludos

2 Me gusta