martes, 24 de junio de 2014

Leer XML desde SQL Server 2008

El siguiente ejemplo lee los archivos XML de una carpeta. Lee el dato 'folio' y 'uuid', a continuación los guarda en una tabla física de la base de datos en donde el folio sea igual al que trae el documento, ademas lee los archivos txt de otra carpeta para saber si existe un archivo de cancelación del mismo numero de folio, si es así revisa si ya trae el dato 'uuid', si no es así crea un nuevo documento con el nuevo dato para que este completo el archivo. A continuación borra el archivo leído. Espero les sirva...

@PathName  VARCHAR(256)='C:\Develop\PAWNTECH\Archivos_FE\',
@PathNameCan  VARCHAR(256)='C:\Develop\PAWNTECH\Txt_FE\PTCancelacion',
@Extension VARCHAR(5)= '.txt'
AS 
BEGIN
 SET NOCOUNT ON;
 --Crea tabla temporal para alojar el archivo XML
 CREATE TABLE #WorkingTable
  (Data XML)
 --Lee los archivos contenidos en la carpeta donde se alojan los documentos XML
 DECLARE  @CMD       VARCHAR(512)
 Declare @Folio VARCHAR(50)
        Declare @UUID VARCHAR(100)
 DECLARE @CommandShell TABLE(Line VARCHAR(512))
 SET @CMD = 'DIR ' + @PathName + ' /B'
 INSERT INTO @CommandShell
  EXEC MASTER..xp_cmdshell   @CMD 
 declare @line as varchar(50) 
 declare @contador as int
 declare @Xpath as varchar(100)
 declare @XpathC as varchar(100)
 declare @sql as varchar(max)
 declare CURSORVC cursor for 
 select line  from @CommandShell 
 SET @contador = 0
 --Abre cursor
 open CURSORVC 
 fetch next from CURSORVC into @line
 while @@fetch_status = 0 
 begin
  set @XpathC = @PathName+@line  
  --Lee El archvio XML y saca el folio y el UUID
  SELECT @sql = 'insert INTO #WorkingTable SELECT * FROM OPENROWSET (BULK '''+ @XpathC+''', SINGLE_BLOB) AS data'
  EXEC sp_sqlexec @sql
  DECLARE @XML AS XML, @hDoc AS INT
  SELECT   @XML = Data FROM #WorkingTable 
  EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML, ''
  set @Folio =( SELECT *
   FROM OPENXML (@hDoc, '/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital',1) 
   with (folio VARCHAR(50) '../../@folio'))
  set @UUID = (SELECT *
   FROM OPENXML (@hDoc, '/cfdi:Comprobante/cfdi:Complemento/tfd:TimbreFiscalDigital',1) 
   with (UUID VARCHAR(50) '@UUID') )
  update dbo.Movimientos set VUUID =@UUID
   where NFolioFactura = @Folio
   --Busca el archvio cacelado
      drop TABLE #txt
      declare @i int
               declare @File varchar(1000)
               CREATE TABLE #txt
               (
                campo1 VARCHAR(max)
                )
            select @File = @PathNameCan + @Folio+@Extension
            exec master..xp_fileexist @File, @i out
            if @i = 1
            begin
         select @File
         declare @sqlc as varchar(max)
         declare @sqlV as varchar(max)
         SELECT @sqlc = 'BULK INSERT #txt
                        FROM '''+ @File+''' WITH
                             (
                              ROWTERMINATOR = '''+'\n'+''',
                              FIRSTROW=7,
                              LASTROW=7
                              )'
          EXEC sp_sqlexec @sqlc
          declare @LeeUUID varchar (50)= (select campo1 from #txt)
          select @LeeUUID
                      if @LeeUUID = 'com:uuid='
                      begin
                      drop table ##MyTable
                      create table ##MyTable 
                      (
                      abc varchar(200),
                       )
                      DECLARE @cmdR as varchar(max)
                      select @cmdR = 'BULK INSERT ##MyTable
                      from '''+@File+'''
                      with (
                      rowterminator='''+'\n'+''',
                      FIRSTROW=1
                       )'
                      EXEC sp_sqlexec @cmdR
                      update ##MyTable set abc ='com:uuid='+ @UUID where abc = 'com:uuid='
                      DECLARE @vid VARCHAR(2)
                      DECLARE @querytextNoVid VARCHAR(100)
                      DECLARE @querytext VARCHAR(100)
                      DECLARE @filelocation VARCHAR(100)
                      DECLARE @cmd2 VARCHAR(255)
                      SET @querytext = '"SELECT abc FROM ##MyTable"'
                      SET @filelocation = '"'+@PathNameCan+''+@Folio+''+@Extension+'"'
                      SET @cmd2 = 'bcp ' + @querytext + ' queryout ' + @filelocation + ' -T -c'
                      EXEC master..XP_CMDSHELL @cmd2
                      declare @Deletetxtx varchar(1000)
                set @Deletetxtx = 'EXEC MASTER..xp_cmdshell "del '+@File+'"'
                EXEC sp_sqlexec @Deletetxtx
                end
                else 
                       print 'Lleno'
                end
  --Elimina el archvio leido
  declare @myquery varchar(1000)
  declare @query varchar(1000)
  declare @name varchar(100)
  set @query = 'EXEC MASTER..xp_cmdshell "del '+@XpathC+'"'
  EXEC sp_sqlexec @query
  EXEC sp_xml_removedocument @hDoc
  set @contador = @contador + 1 
  fetch next from CURSORVC into  @line
 end
--Cierra Cursor
close CURSORVC 
deallocate CURSORVC
END
XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<cfdi:Comprobante xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cfdi="http://www.sat.gob.mx/cfd/3" xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd" version="3.2" serie="NJ" folio="808" fecha="2014-06-24T10:37:19" sello="" formaDePago="PAGO EN UNA SOLA EXHIBICION" noCertificado="7" certificado="" condicionesDePago="CONTADO" subTotal="86.21" descuento="0" total="100.00" metodoDePago="EFECTIVO" tipoDeComprobante="ingreso" LugarExpedicion="">
     <cfdi:Emisor rfc="" nombre="">
           <cfdi:DomicilioFiscal calle="" noExterior="" noInterior="" colonia="" municipio="TLALPAN" estado="" pais="MÉXICO" codigoPostal=""/>
        <cfdi:ExpedidoEn calle="" noExterior="" colonia="" estado="LOS REYES" pais=""/>
<cfdi:RegimenFiscal Regimen="REGIMEN GENERAL DE LEY PERSONAS MORALES"/>
>  
</cfdi:Comprobante>

4 comentarios:

  1. Me lanza un error: XML parsing error: Referencia a un prefijo de espacio de nombres no declarado: 'cfdi'.

    ResponderBorrar
  2. Hola tade pero sin sueño,

    aqui un metodo para sacar un dato de un xml especificamente el CFDI

    DECLARE
    @xml as XML ,
    @ruta AS varchar(100)
    declare @sql as varchar(max)
    SET @ruta='c:\XML\prueba.xml'

    -- Codigo Dinamico
    DECLARE @SQL_BULK VARCHAR(MAX)
    CREATE TABLE #WorkingTable
    (Data XML)
    SELECT @sql = 'insert INTO #WorkingTable SELECT * FROM OPENROWSET (BULK '''+ @ruta+''', SINGLE_BLOB) AS data'
    EXEC sp_sqlexec @sql

    SELECT @xml=Data FROM #WorkingTable
    SELECT @xml ;
    WITH xmlnamespaces('http://www.sat.gob.mx/cfd/3' AS cfdi)
    SELECT
    comprobante.value('@NumCtaPago', 'varchar(100)') 'NumCtaPago'
    --,
    --comprobante.value('cfde:Emisor/cfdi:DomicilioFiscal/@codigoPostal)[1]','int') 'CP'
    FROM @xml.nodes ('/cfdi:Comprobante') t1(comprobante)

    ResponderBorrar
  3. intente hacerlo pero sacando el RFC del emisor, pero no me sale. Me ayudas?

    ResponderBorrar
  4. Tienes que agregar al xmlnamespace lo restante, quedaria asi mas o menos y ya puedes hacer la consulta

    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)
    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',

    ResponderBorrar