Ver Mensaje Individual
  #4  
Antiguo 22-02-2012
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Reputación: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Ya logré hacer un documento XML de prueba y validarlo contra el esquema del Impuesto a los Depósitos en Efectivo del SAT. Este es el código que escribí para ello (creo que le puede servir a cualquiera que desee crear y validar documentos XML ):

Código Delphi [-]
Uses
  COMObj, XMLDoc;

procedure TfmPrincipal.btGenerarClick(Sender: TObject);
Var
  Elemento, Error, XML :OLEVariant;
  I, J :Integer;

  // Función para crear y añadir un nuevo elemento al documento
  Function CrearElemento (Const Nombre :String) :OLEVariant;
  Begin
    Result := XML.CreateElement (Nombre);

    If Not VarIsEmpty (Elemento) Then
      Elemento.AppendChild (Result);

    Elemento := Result;
  End;
begin
  { Empezamos un nuevo objeto documento obteniendo una interfaz
    IXMLDOMDocument de MSXML 4.0, primera versión en soportar esquemas
    XML (XSD) }
  XML := CreateOLEObject ('MSXML2.DOMDocument.4.0');

  // Agregamos el prólogo o cabecera del archivo
  XML.AppendChild (XML.CreateProcessingInstruction ('xml',
    'version="1.0" encoding="UTF-8"'));

  { Agregamos el elemento principal correspondiente a una declaración
    mensual y establecemos sus atributos requeridos }
  XML.DocumentElement := CrearElemento (
    'DeclaracionInformativaMensualIDE');
  Elemento.SetAttribute ('version', '1.1');
  Elemento.SetAttribute ('rfcDeclarante', 'XXXX010101XX');
  Elemento.SetAttribute ('denominacion',
    'Cooperativa X (documento de prueba)');

  { Agregamos el elemento RepresentanteLegal, establecemos su atributo
    requerido rfc y le añadimos los elementos que guardan el nombre del
    representante }
  CrearElemento ('RepresentanteLegal');
  Elemento.SetAttribute ('rfc', 'XXXX010101XX1');
  CrearElemento ('Nombre');
  CrearElemento ('NombreCompleto');
  Elemento.Text := 'Nina Vida';

  { Regresamos al elemento principal y agregamos el elemento que indica que
    se trata de una declaración normal (no complementaria) y establecemos
    sus atributos requeridos }
  Elemento := XML.DocumentElement;
  CrearElemento ('Normal');
  Elemento.SetAttribute ('ejercicio', '2011');
  Elemento.SetAttribute ('periodo', '1');  // enero

  { Regresamos al elemento principal y agregamos el elemento que contendrá
    el listado de información monetaria para una entidad "distinta de las
    de crédito", que el autor de este ejemplo entiende como "no bancos", es
    decir, cooperativas de ahorro y similares. }
  Elemento := XML.DocumentElement;
  CrearElemento ('InstitucionDistintaDeCredito');

  { Agregamos 6 registros monetarios dentro de tres fechas distintas
    (anteayer, ayer y hoy).  Cada fecha corresponde a un elemento
    "ReporteDeRecaudacionYEnteroDiaria", y cada registro monetario es un
    elemento "RegistroDeDetalle" que corresponde a un cuentacorrentista
    (titular de una cuenta). }
  For I := 1 To 3 Do
  Begin
    CrearElemento ('ReporteDeRecaudacionYEnteroDiaria');
    Elemento.SetAttribute ('fechaDeCorte', FormatDateTime ('yyyy-mm-dd',
      Date - (3 - I)));  // Fechas en formato ISO

    For J := 1 To 2 Do
    Begin
      CrearElemento ('RegistroDeDetalle');
      CrearElemento ('PersonaFisica');
      Elemento.SetAttribute ('rfc', 'XXXX010101XX1');
      CrearElemento ('Nombre');
      CrearElemento ('NombreCompleto');
      Elemento.Text := 'Juan Pérez';

      // Subimos dos niveles (a PersonaFisica)
      Elemento := Elemento.ParentNode.ParentNode;
      
      CrearElemento ('Domicilio');
      CrearElemento ('DomicilioCompleto');
      Elemento.Text := 'Av. Madero #1010, col. Centro, C.P. 58000';

      // Subimos tres niveles (a RegistroDeDetalle)
      Elemento := Elemento.ParentNode.ParentNode.ParentNode;
      
      CrearElemento ('DepositoEnEfectivo');
      Elemento.SetAttribute ('montoExcedente', '100');
      Elemento.SetAttribute ('impuestoDeterminado', '3');
      Elemento.SetAttribute ('impuestoRecaudado', '3');
      Elemento.SetAttribute ('recaudacionPendiente', '0');
      Elemento.SetAttribute ('remanentePeriodosAnteriores', '0');

      // Subimos dos niveles (a ReporteDeRecaudacionYEnteroDiaria)
      Elemento := Elemento.ParentNode.ParentNode;
    End;

    // Subimos un nivel (a InstitucionDistintaDeCredito)
    Elemento := Elemento.ParentNode;
  End;

  { Último elemento hijo de InstitucionDistintaDeCredito y final de todo
    el documento }
  CrearElemento ('Totales');
  Elemento.SetAttribute ('operacionesRelacionadas', '50');  // 50 depósitos
  Elemento.SetAttribute ('importeExcedenteDepositos', '600');
  Elemento.SetAttribute ('importeDeterminadoDepositos', '18');
  Elemento.SetAttribute ('importeRecaudadoDepositos', '18');
  Elemento.SetAttribute ('importePendienteRecaudacion', '0');
  Elemento.SetAttribute ('importeRemanenteDepositos', '0');
  Elemento.SetAttribute ('importeEnterado', '0');

  { Asignamos al documento el esquema de definición y lo validamos contra
    éste (el archivo ide_20080818.xsd se encuentra en el mismo directorio
    de la aplicación) }
  XML.Schemas := CreateOLEObject ('MSXML2.XMLSchemaCache.4.0');
  XML.Schemas.Add ('', 'ide_20080818.xsd');
  Error := XML.Validate;

  { En caso de que el documento formado no cumpla con el esquema XSD,
    mostraremos la razón de ello en el cuadro de texto TEdit edError }
  If Error.ErrorCode <> 0 Then
    edError.Text := Error.Reason;

  { Tomamos el contenido del documento, le damos sangrado con la función
    FormatXMLData para hacerlo más legible y lo insertamos dentro del
    cuadro de texto TMemo mmContenido.  NOTA: En MSXML la propiedad XML
    de un documento regresa su contenido sin el atributo "encoding", pero
    internamente lo mantiene y aparece como debe ser al guardar el
    archivo. }
  mmContenido.Text := FormatXMLData (XML.XML);
  mmContenido.SetFocus;  // Damos el foco al control mmContenido

  XML.Save ('PruebaIDE.xml');  // Guardamos el archivo a disco
end;

El programa XSD Diagram que recomendó Eliseo es ligero y sencillo, me bastó para analizar y entender en buena medida la estructura que debe cumplir una declaración mensual del IDE. Lo malo es que en el mismo archivo ide_20080818.xsd el SAT define también la estructura para una declaración anual, es decir, el archivo de esquema establece dos posibles nodos primarios: DeclaracionInformativaMensualIDE DeclaracionInformativaAnualIDE (desconozco si eso está fuera de norma), y tanto XSD Diagram como XML Mapper solamente muestran la estructura que se desprende del primero. Supongo que tendré que recortar la segunda estructura del esquema y meterla en otro archivo XSD para poder analizarla con la misma facilidad.

La versión gratuita de Altova no me gustó, porque además de pesada no dan clave para registro a menos que se tenga una cuenta de correo "corporativa":
Cita:
Dear Osama Bin Laden,

Thank you for your interest in Altova software. Unfortunately, we are unable to process key-code requests from unverified email domains and webmail accounts, such as hotmail.com, gmail.com, etc.

To receive your free 30-day trial license key-code, please enter your corporate email address [...]
Mi siguiente paso es hacer pruebas adicionales de generación y validación del XML tomando información más parecida a la real, tal como será proporcionada por el contador de la cooperativa. Pero también ya voy a hacer la solicitud del Socket de Seguridad, sólo que para esto debo decirle al SAT cuál es la IP pública (o "nateada") que usaré. Quiero instalar una provisional para hacer pruebas, ¿qué instrumento me recomiendan?

Saludos.

Al González.
Responder Con Cita