Uso de XSL para transformar la factura electronica XML

Contenido/contents:
Introducion
Cadena Original
Verificacion de sello
Impresion
Informe
Pagina anterior/Previous page

Introduccion
Cadena Original
Esta es mi primera prueba con XSLT por lo cual este archivo de transformacion esta muy extenso. Estoy seguro de que se pudiera siplificar no repitiendo lo mismo para cada atributo pero mientras no descubra la manera asi lo dejo.
5/Jun/2006 Esta ya es mi segunda version, gracias a David Ongay por detectar varios errores, esta version ya no requiera que exista Addenda para generar la cadena correcta, y ademas correji unos pequeñ errores de dedo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<xsl:stylesheet version = '1.0'
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
 
<xsl:output method = "text" /> 
 
<xsl:template match="/">|<xsl:apply-templates select="//Comprobante"/>||</xsl:template>
 
<xsl:template match="Comprobante">
      <xsl:if test="@version">|<xsl:value-of select="@version"/></xsl:if>
      <xsl:if test="@serie">|<xsl:value-of select="@serie"/></xsl:if>
      <xsl:if test="@folio">|<xsl:value-of select="@folio"/></xsl:if>
      <xsl:if test="@fecha">|<xsl:value-of select="@fecha"/></xsl:if>
      <xsl:if test="@noAprobacion">|<xsl:value-of select="@noAprobacion"/></xsl:if>
      <xsl:if test="@anoAprobacion">|<xsl:value-of select="@anoAprobacion"/></xsl:if>
      <xsl:if test="@tipoDeComprobante">|<xsl:value-of select="@tipoDeComprobante"/></xsl:if>
      <xsl:if test="@formaDePago">|<xsl:value-of select="@formaDePago"/></xsl:if>
      <xsl:if test="@condicionesDePago">|<xsl:value-of select="@condicionesDePago"/></xsl:if>
      <xsl:if test="@subTotal">|<xsl:value-of select="@subTotal"/></xsl:if>
      <xsl:if test="@descuento">|<xsl:value-of select="@descuento"/></xsl:if>
      <xsl:if test="@total">|<xsl:value-of select="@total"/></xsl:if>
      <xsl:apply-templates select="//Emisor"/>
      <xsl:apply-templates select="//DomicilioFiscal"/>
      <xsl:apply-templates select="//ExpedidoEn"/>
      <xsl:apply-templates select="//Receptor"/>
      <xsl:apply-templates select="//Domicilio"/>
      <xsl:apply-templates select="//Concepto"/>
      <xsl:apply-templates select="//Impuestos"/>
</xsl:template>
 
<xsl:template match="Emisor">
      <xsl:if test="@rfc">|<xsl:value-of select="@rfc"/></xsl:if>
      <xsl:if test="@nombre">|<xsl:value-of select="@nombre"/></xsl:if>
</xsl:template>
 
<xsl:template match="DomicilioFiscal">
      <xsl:if test="@calle">|<xsl:value-of select="@calle"/></xsl:if>
      <xsl:if test="@noExterior">|<xsl:value-of select="@noExterior"/></xsl:if>
      <xsl:if test="@noInterior">|<xsl:value-of select="@noInterior"/></xsl:if>
      <xsl:if test="@colonia">|<xsl:value-of select="@colonia"/></xsl:if>
      <xsl:if test="@localidad">|<xsl:value-of select="@localidad"/></xsl:if>
      <xsl:if test="@referencia">|<xsl:value-of select="@referencia"/></xsl:if>
      <xsl:if test="@municipio">|<xsl:value-of select="@municipio"/></xsl:if>
      <xsl:if test="@estado">|<xsl:value-of select="@estado"/></xsl:if>
      <xsl:if test="@pais">|<xsl:value-of select="@pais"/></xsl:if>
      <xsl:if test="@codigoPostal">|<xsl:value-of select="@codigoPostal"/></xsl:if>
</xsl:template>
 
<xsl:template match="ExpedidoEn">
      <xsl:if test="@calle">|<xsl:value-of select="@calle"/></xsl:if>
      <xsl:if test="@noExterior">|<xsl:value-of select="@noExterior"/></xsl:if>
      <xsl:if test="@noInterior">|<xsl:value-of select="@noInterior"/></xsl:if>
      <xsl:if test="@colonia">|<xsl:value-of select="@colonia"/></xsl:if>
      <xsl:if test="@localidad">|<xsl:value-of select="@localidad"/></xsl:if>
      <xsl:if test="@refrencia">|<xsl:value-of select="@referencia"/></xsl:if>
      <xsl:if test="@municipio">|<xsl:value-of select="@municipio"/></xsl:if>
      <xsl:if test="@estado">|<xsl:value-of select="@estado"/></xsl:if>
      <xsl:if test="@pais">|<xsl:value-of select="@pais"/></xsl:if>
      <xsl:if test="@codigoPostal">|<xsl:value-of select="@codigoPostal"/></xsl:if>
</xsl:template>
 
<xsl:template match="Receptor">
      <xsl:if test="@rfc">|<xsl:value-of select="@rfc"/></xsl:if>
      <xsl:if test="@nombre">|<xsl:value-of select="@nombre"/></xsl:if>
</xsl:template>
 
<xsl:template match="Domicilio">
      <xsl:if test="@calle">|<xsl:value-of select="@calle"/></xsl:if>
      <xsl:if test="@noExterior">|<xsl:value-of select="@noExterior"/></xsl:if>
      <xsl:if test="@noInterior">|<xsl:value-of select="@noInterior"/></xsl:if>
      <xsl:if test="@colonia">|<xsl:value-of select="@colonia"/></xsl:if>
      <xsl:if test="@localidad">|<xsl:value-of select="@localidad"/></xsl:if>
      <xsl:if test="@refrencia">|<xsl:value-of select="@referencia"/></xsl:if>
      <xsl:if test="@municipio">|<xsl:value-of select="@municipio"/></xsl:if>
      <xsl:if test="@estado">|<xsl:value-of select="@estado"/></xsl:if>
      <xsl:if test="@pais">|<xsl:value-of select="@pais"/></xsl:if>
      <xsl:if test="@codigoPostal">|<xsl:value-of select="@codigoPostal"/></xsl:if>
</xsl:template>
 
<xsl:template match="Concepto">
      <xsl:if test="@cantidad">|<xsl:value-of select="@cantidad"/></xsl:if>
      <xsl:if test="@unidad">|<xsl:value-of select="@unidad"/></xsl:if>
      <xsl:if test="@noIdentificacion">|<xsl:value-of select="@noIdentificacion"/></xsl:if>
      <xsl:if test="@descripcion">|<xsl:value-of select="@descripcion"/></xsl:if>
      <xsl:if test="@valorUnitario">|<xsl:value-of select="@valorUnitario"/></xsl:if>
      <xsl:if test="@importe">|<xsl:value-of select="@importe"/></xsl:if>
      <xsl:apply-templates select="InformacionAduanera"/>
</xsl:template>
 
<xsl:template match="Impuestos">
      <xsl:apply-templates select="//Retencion"/>
      <xsl:if test="@totalImpuestosRetenidos">|<xsl:value-of select="@totalImpuestosRetenidos"/></xsl:if>
      <xsl:apply-templates select="//Traslado"/>
      <xsl:if test="@totalImpuestosTrasladados">|<xsl:value-of select="@totalImpuestosTrasladados"/></xsl:if>
  </xsl:template>
 
<xsl:template match="InformacionAduanera">
      <xsl:if test="@numero">|<xsl:value-of select="@numero"/></xsl:if>
      <xsl:if test="@fecha">|<xsl:value-of select="@fecha"/></xsl:if>
      <xsl:if test="@aduana">|<xsl:value-of select="@aduana"/></xsl:if>
</xsl:template>
 
<xsl:template match="Retencion">
      <xsl:if test="@impuesto">|<xsl:value-of select="@impuesto"/></xsl:if>
      <xsl:if test="@importe">|<xsl:value-of select="@importe"/></xsl:if>
</xsl:template>
 
<xsl:template match="Traslado">
      <xsl:if test="@impuesto">|<xsl:value-of select="@impuesto"/></xsl:if>
      <xsl:if test="@tasa">|<xsl:value-of select="@tasa"/></xsl:if>
      <xsl:if test="@importe">|<xsl:value-of select="@importe"/></xsl:if>
</xsl:template>
 
</xsl:stylesheet>
Vamor a aplicar las reglas de transformacion anteriores al siguiente archivo XML.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?xml version="1.0"
    encoding="UTF-8"?>
 
<Comprobante xmlns="http://www.sat.gob.mx/cfd/2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.sat.gob.mx/cfd/2  http://www.sat.gob.mx/sitio_internet/cfd/2/cfdv2.xsd"
    version="2.0"
    serie="FAXA"
    folio="051661"
    fecha="2006-11-20T08:50:48"
    sello="33HZqWoHi7u4gWkcnipTEiCz7UFOPGQ1NYqHmOyTGxpiJE8dyEBew8QS4f99zYz8QqXFvP0IEkWVCaKPBKm/6tClIdK/jJFZGxlcP/QCKfnBnMF/ktzukLLxHhwfK+StNpEkx90riDTITVv+wcmRy+kGrxlTB7N6gr1sK+tHBBI="
    noAprobacion="2951"
    anoAprobacion="2006"
    tipoDeComprobante="ingreso"
    formaDePago="EL PAGO DE ESTA FACTURA (CONTRAPRESTACION) SE EFECTUARA EN UNA SOLA EXHIBICION, SI POR ALGUNA RAZON NO FUERA ASI, EMITIREMOS LOS COMPROBANTES DE LAS PARCIALIDADES RESPECTIVAS"
    noCertificado="00001000000000823747"
    subTotal="43824.69"
    total="50398.39">
<Emisor rfc="FJC780315E91"
    nombre="FABRICA DE JABON, LA CORONA, S.A. DE C.V.">
<DomicilioFiscal calle="CARLOS B. ZETINA"
    noExterior="80"
    colonia="INDUSTRIAL XALOSTOC"
    municipio="ECATEPEC"
    estado="MEXICO"
    pais="MEXICO"
    codigoPostal="55348"/>
<ExpedidoEn calle="CARLOS B.ZETINA NO.80"
    municipio="XALOSTOC, EDO. DE MEXICO"
    estado="EDO. DE MEXICO"
    pais="MEXICO"
    codigoPostal="55348"/>
</Emisor>
<Receptor rfc="NWM9709244W4"
    nombre="NUEVA WAL-MART DE MEXICO SRL DE CV">
<Domicilio calle="KM.40.5 CARRT. MEXICO-QUERETARO"
    colonia="."
    municipio="CUAUTITLAN IZCALLI       MEX."
    estado="MEXICO"
    pais="MEXICO"/>
</Receptor>
<Conceptos>
<Concepto cantidad="22"
    descripcion="TEPEYAC 25P 400 G C/ENV"
    valorUnitario="110.97"
    importe="2441.34"/>
<Concepto cantidad="11"
    descripcion="ZOTE AZUL 25P 400 G."
    valorUnitario="110.97"
    importe="1220.67"/>
<Concepto cantidad="22"
    descripcion="ZOTE BCO. 25P 400 G"
    valorUnitario="110.97"
    importe="2441.34"/>
<Concepto cantidad="7"
    descripcion="ZOTE BCO. 50P 200 G"
    valorUnitario="110.97"
    importe="776.79"/>
<Concepto cantidad="44"
    descripcion="ZOTE ROSA 25P 400 G"
    valorUnitario="110.97"
    importe="4882.68"/>
<Concepto cantidad="6"
    descripcion="ZOTE ROSA 50P 200 G"
    valorUnitario="110.97"
    importe="665.82"/>
<Concepto cantidad="12"
    descripcion="ROMA 4P 5 KGS"
    valorUnitario="218.34"
    importe="2620.08"/>
<Concepto cantidad="24"
    descripcion="ROMA 10P 2 KGS"
    valorUnitario="219.74"
    importe="5273.64"/>
<Concepto cantidad="120"
    descripcion="ROMA 10P 1 KG"
    valorUnitario="111.29"
    importe="13354.2"/>
<Concepto cantidad="12"
    descripcion="FOCA 10P 2 KGS"
    valorUnitario="233.87"
    importe="2806.38"/>
<Concepto cantidad="10"
    descripcion="BLANCA NIEVES 10P 2 KGS"
    valorUnitario="201.47"
    importe="2014.65"/>
<Concepto cantidad="40"
    descripcion="BLANCA NIEVES 10P 1 KG"
    valorUnitario="102.15"
    importe="4086.0"/>
<Concepto cantidad="5"
    descripcion="BRILOZA 10P 1 KG"
    valorUnitario="102.15"
    importe="510.75"/>
<Concepto cantidad="6"
    descripcion="FOCA 12B 1LT"
    valorUnitario="121.73"
    importe="730.35"/>
</Conceptos>
<Impuestos>
<Traslados>
<Traslado impuesto="IVA"
    tasa="15.0"
    importe="6573.7"/>
</Traslados>
</Impuestos>
<Addenda>
<edi>
UNA:+.?'UNB+UNOB:1+JABON-CORONA:ZZ+925485MX00:8+061211:1150+2372'UNG+INVOIC+JABON-CORONA:ZZ+925485MX00:8+061211:1150+2372+UN+D:01B:AMC002'UNH+2372+INVOIC:D:01B:UN:AMC002'BGM+380+051661+9'DTM+137:20061120085048:204'FTX+ZZZ+++(CINCUENTA MIL TRESCIENTOS NOVENTA Y OCHO PESOS 39/100 M.N.)'RFF+ON:1800131675'DTM+171:20061119:102'RFF+BT:FAXA'RFF+ATZ:12345678'NAD+BY+7507003100001::9++NUEVA WAL MART DE MEXICO S DE RL DE:CV+NEXTENGO NO 78:SANTA CRUZ ACAYUCAN+AZCAPOTZALCO+DF+02770'RFF+GN:NWM9709244W4'NAD+SU+7504000065005::9++FABRICA DE JABON LA CORONA,SA DE CV+CARLOS B ZETINA NO 80+FRACC IND XALOSTOC+MC+55348'RFF+GN:FJC780315E91'RFF+IA:172042130'NAD+II+7504000065005::9++FABRICA DE JABON LA CORONA,SA DE CV+CARLOS B.ZETINA NO.80:COL INDUSTRIAL XALOSTOC+XALOSTOC, EDO. DE MEXICO+MC+55348'NAD+ST+7507003176426::9++AURRERA NO.379:NUEVA WAL-MART DE MEXICO SRL DE CV+KM.40.5 CARRT. MEXICO-QUERETARO:.+CUAUTITLAN IZCALLI+MC+54830'CUX+2:MXN:4++1'PAT+1++5:3:D:30'PCD+12:0'LIN+1++7501026006340 :SRV::9'PIA+1+121:SA'IMD+F++:::TEPEYAC 25P 400 G C/ENV'QTY+47:22:CA'QTY+59:25:EA'MOA+203:2441.34'PRI+AAA:110.97::::CA'TAX+7+VAT+++:::15.0'MOA+124:366.2'LIN+2++7501026005404 :SRV::9'PIA+1+523:SA'IMD+F++:::ZOTE AZUL 25P 400 G.'QTY+47:11:CA'QTY+59:25:EA'MOA+203:1220.67'PRI+AAA:110.97::::CA'TAX+7+VAT+++:::15.0'MOA+124:183.1'LIN+3++7501026005374 :SRV::9'PIA+1+530:SA'IMD+F++:::ZOTE BCO. 25P 400 G'QTY+47:22:CA'QTY+59:25:EA'MOA+203:2441.34'PRI+AAA:110.97::::CA'TAX+7+VAT+++:::15.0'MOA+124:366.2'LIN+4++7501026005381 :SRV::9'PIA+1+539:SA'IMD+F++:::ZOTE BCO. 50P 200 G'QTY+47:7:CA'QTY+59:50:EA'MOA+203:776.79'PRI+AAA:110.97::::CA'TAX+7+VAT+++:::15.0'MOA+124:116.52'LIN+5++7501026005671 :SRV::9'PIA+1+560:SA'IMD+F++:::ZOTE ROSA 25P 400 G'QTY+47:44:CA'QTY+59:25:EA'MOA+203:4882.68'PRI+AAA:110.97::::CA'TAX+7+VAT+++:::15.0'MOA+124:732.4'LIN+6++7501026005688 :SRV::9'PIA+1+573:SA'IMD+F++:::ZOTE ROSA 50P 200 G'QTY+47:6:CA'QTY+59:50:EA'MOA+203:665.82'PRI+AAA:110.97::::CA'TAX+7+VAT+++:::15.0'MOA+124:99.87'LIN+7++7501026004483 :SRV::9'PIA+1+40444:SA'IMD+F++:::ROMA 4P 5 KGS'QTY+47:12:CA'QTY+59:4:EA'MOA+203:2620.08'PRI+AAA:218.34::::CA'TAX+7+VAT+++:::15.0'MOA+124:393.01'LIN+8++7501026004537 :SRV::9'PIA+1+40445:SA'IMD+F++:::ROMA 10P 2 KGS'QTY+47:24:CA'QTY+59:10:EA'MOA+203:5273.64'PRI+AAA:219.735::::CA'TAX+7+VAT+++:::15.0'MOA+124:791.05'LIN+9++7501026004605 :SRV::9'PIA+1+40446:SA'IMD+F++:::ROMA 10P 1 KG'QTY+47:120:CA'QTY+59:10:EA'MOA+203:13354.2'PRI+AAA:111.285::::CA'TAX+7+VAT+++:::15.0'MOA+124:2003.13'LIN+10++7501026026539 :SRV::9'PIA+1+42671:SA'IMD+F++:::FOCA 10P 2 KGS'QTY+47:12:CA'QTY+59:10:EA'MOA+203:2806.38'PRI+AAA:233.865::::CA'TAX+7+VAT+++:::15.0'MOA+124:420.96'LIN+11++7501026027529 :SRV::9'PIA+1+42744:SA'IMD+F++:::BLANCA NIEVES 10P 2 KGS'QTY+47:10:CA'QTY+59:10:EA'MOA+203:2014.65'PRI+AAA:201.465::::CA'TAX+7+VAT+++:::15.0'MOA+124:302.2'LIN+12++7501026027536 :SRV::9'PIA+1+42765:SA'IMD+F++:::BLANCA NIEVES 10P 1 KG'QTY+47:40:CA'QTY+59:10:EA'MOA+203:4086.0'PRI+AAA:102.15::::CA'TAX+7+VAT+++:::15.0'MOA+124:612.9'LIN+13++7501026027727 :SRV::9'PIA+1+43064:SA'IMD+F++:::BRILOZA 10P 1 KG'QTY+47:5:CA'QTY+59:10:EA'MOA+203:510.75'PRI+AAA:102.15::::CA'TAX+7+VAT+++:::15.0'MOA+124:76.61'LIN+14++7501026028007 :SRV::9'PIA+1+52624:SA'IMD+F++:::FOCA 12B 1LT'QTY+47:6:CA'QTY+59:12:EA'MOA+203:730.35'PRI+AAA:121.725::::CA'TAX+7+VAT+++:::15.0'MOA+124:109.55'UNS+S'CNT+11:341'CNT+2:14'MOA+9:50398.39'MOA+79:43824.69'MOA+125:43824.69'TAX+7+VAT+++:::15.0'MOA+124:6573.7'UNT+153+2372'UNE+4+2372'UNZ+1+2372'</edi>
</Addenda>
</Comprobante>
Para aplicar las reglas usamos el comando xsltproc dando como primer argumento el archivo con las reglas de transofrmacion XSL y como segundo el nombre del archivo con la factura XML.
[web@web sat]$ xsltproc cadena_original.xsl fact.xml
||2.0|FAXA|051661|2006-11-20T08:50:48|2951|2006|ingreso|EL PAGO DE ESTA FACTURA (CONTRAPRESTACION) SE EFECTUARA EN UNA SOLA EXHIBICION, SI POR ALGUNA RAZON NO FUERA ASI, EMITIREMOS LOS COMPROBANTES DE LAS PARCIALIDADES RESPECTIVAS|43824.69|50398.39|FJC780315E91|FABRICA DE JABON, LA CORONA, S.A. DE C.V.|CARLOS B. ZETINA|80|INDUSTRIAL XALOSTOC|ECATEPEC|MEXICO|MEXICO|55348|CARLOS B.ZETINA NO.80|XALOSTOC, EDO. DE MEXICO|EDO. DE MEXICO|MEXICO|55348|NWM9709244W4|NUEVA WAL-MART DE MEXICO SRL DE CV|KM.40.5 CARRT. MEXICO-QUERETARO|.|CUAUTITLAN IZCALLI       MEX.|MEXICO|MEXICO|22|TEPEYAC 25P 400 G C/ENV|110.97|2441.34|11|ZOTE AZUL 25P 400 G.|110.97|1220.67|22|ZOTE BCO. 25P 400 G|110.97|2441.34|7|ZOTE BCO. 50P 200 G|110.97|776.79|44|ZOTE ROSA 25P 400 G|110.97|4882.68|6|ZOTE ROSA 50P 200 G|110.97|665.82|12|ROMA 4P 5 KGS|218.34|2620.08|24|ROMA 10P 2 KGS|219.74|5273.64|120|ROMA 10P 1 KG|111.29|13354.2|12|FOCA 10P 2 KGS|233.87|2806.38|10|BLANCA NIEVES 10P 2 KGS|201.47|2014.65|40|BLANCA NIEVES 10P 1 KG|102.15|4086.0|5|BRILOZA 10P 1 KG|102.15|510.75|6|FOCA 12B 1LT|121.73|730.35|IVA|15.0|6573.7||
Ya con esa cadena original podemos aplicar las reglas para calcular el sello. El primer paso es calcular el hash md5.
[web@web sat]$ xsltproc cadena_original.xsl fact.xml | md5sum | cut -f1 -d \ 
6b927330e1d0b977c0846910f0559e07
Este hash ya se puede sellar con el certificado (que ya tengo convertido en formato PEM) y ademas codificarlo en formato base64 porque el sello lo deja en binario.
Openssl tiene la facilidad de calcular el md5 y de sellarlo en un mismo paso, por lo cual ya no hace falta calcular el md5 en un paso previo.
[web@web sat]$ xsltproc cadena_original.xsl fact.xml | openssl dgst -md5 -sign AAA010101AAA.key.pem | openssl enc -base64 -A
33HZqWoHi7u4gWkcnipTEiCz7UFOPGQ1NYqHmOyTGxpiJE8dyEBew8QS4f99zYz8QqXFvP0IEkWVCaKPBKm/6tClIdK/jJFZGxlcP/QCKfnBnMF/ktzukLLxHhwfK+StNpEkx90riDTITVv+wcmRy+kGrxlTB7N6gr1sK+tHBBI=
Si son observadores veran que el sello recien calculado es el mismo que esta almacenado en el atributo "sello" del XML.
Verificacion del sello
Ahora voy a simular lo que hay que hacer para validar que el sello es correcto, es decir, es el sello correspondiente a la factura firmada por el certificado correspondiente.
Este es una pequen˜a hoja de conversion para extraer el campo del sello.
1
2
3
4
5
6
7
8
9
10
<xsl:stylesheet version = '1.0'
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
 
<xsl:output method = "text" /> 
 
<xsl:template match="Comprobante">
      <xsl:value-of select="@sello"/>
</xsl:template>
 
</xsl:stylesheet>
Para aplicar las reglas usamos el comando xsltproc dando como primer argumento el archivo con las reglas de transofrmacion XSL y como segundo el nombre del archivo con la factura XML.
[web@web sat]$ xsltproc sello.xsl fact.xml
Rp6QIcD0fJIpLRCUqatx7RM7haGH8kdyiW7cwb7h7R0234uK55M5u8S1tjYYYc7PnL6QjDvyRnTB8DFcvKcHIHO9VQIfinv4rM2S8krh0uK4FjemYNcmjvfYdzcqduj9v1YBj6FvNMatwOg/6ns9j+9WscQ/L5Q1yyB4Bd0p240=
Ahora este campo del sello obtenido del archivo XML lo de-codificamos del codigo base64 y lo dejamos nuevamente como el sello en binario y lo dejamos en un archivo temporal.
[web@web sat]$ xsltproc /home/httpd/sat/sello.xsl fact.xml | openssl enc -base64 -d -A -out sello
Ahora volvemos a 'firmar' pero con la llave publica y verificamos que el sello obtenido coincida con el enviado.
[web@web sat]$ xsltproc cadena_original.xsl fact.xml | openssl dgst -md5 -verify AAA010101AAA.cer.pem -signature sello
Verified OK
Generacion de archivo para impresion
Con el siguiente arhivo de transformacion genero un archivo HTML para consultar en un formato 'agradable al usuario' el contenido de la factura XML.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<xsl:stylesheet version = '1.0'
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
 
<xsl:output method = "html" /> 
 
<xsl:template match="/Comprobante">
   <html>
   <head>
   <link rel="STYLESHEET" media="screen" type="text/css" href="factura.css"/>
   <title>Factura Electronica <xsl:value-of select="@serie"/><xsl:value-of select="@folio"/></title>
   </head>
   <body>
   <table width="100%" border="1">
      <tr><td colspan="2" align="right">
          <table border="1">
               <tr><th class="h1">Serie</th><td class="h1"><xsl:value-of select="@serie"/></td></tr>
               <tr><th class="h1">Folio</th><td class="h1"><xsl:value-of select="@folio"/></td></tr>
               <tr><th class="h1">Fecha</th><td class="h1"><xsl:value-of select="@fecha"/></td></tr>
               <tr><th class="h1">Aprobacion</th><td class="h1"><xsl:value-of select="@noAprobacion"/></td></tr>
           </table>
           </td>
           </tr>
      <tr><td width="50%">
           <table width="100%" border="1"><tr><th colspan="2" class="h1">Emisor</th></tr>
             <tr><th>RFC</th><td><xsl:value-of select="Emisor/@rfc"/></td></tr>
             <tr><th>Nombre</th><td><xsl:value-of select="Emisor/@nombre"/></td></tr>
             <tr><th colspan="2" class="h2">Domiclio</th></tr>
             <tr><td colspan="2"><xsl:value-of select="Emisor/DomicilioFiscal/@calle"/> # <xsl:value-of select="Emisor/DomicilioFiscal/@noExterior"/> - <xsl:value-of select="Emisor/DomicilioFiscal/@noEInterior"/></td></tr>
             <tr><td colspan="2"><xsl:value-of select="Emisor/DomicilioFiscal/@colonia"/></td></tr>
             <tr><td colspan="2"><xsl:value-of select="Emisor/DomicilioFiscal/@localidad"/></td></tr>
             <tr><td colspan="2"><xsl:value-of select="Emisor/DomicilioFiscal/@referencia"/></td></tr>
             <tr><td colspan="2"><xsl:value-of select="Emisor/DomicilioFiscal/@municipio"/>
                 <xsl:if test="Emisor/DomicilioFiscal/@codigoPostal"> CODIGO POSTAL <xsl:value-of select="Emisor/DomicilioFiscal/@codigoPostal"/></xsl:if>
                 </td></tr>
             <tr><td colspan="2"><xsl:value-of select="Emisor/DomicilioFiscal/@estado"/></td></tr>
             <tr><td colspan="2"><xsl:value-of select="Emisor/DomicilioFiscal/@pais"/></td></tr>
             </table>
          </td>
          <td>
          <table width="100%" border=