Leggere una fattura xml firmata

Buongiorno a tutti ragazzi, qualcuno ha capito come leggere i dati xml di una fattura firmata .p7m?

Non riesco nemmeno con qualcosa di questo tipo:

inizio=InStr(s,"<?xml") fine=instr(s,"</p:FatturaElettronica>")

Il motore xml mi va in nil… :frowning:

Qualche dritta? Grazie

Prova con il terminale (shell)
openssl smime -verify -noverify -in documento.estensione.p7m -inform DER -out documento.estensione
dove documento.estensione la tua fattura (comprensiva di percorso)

[quote=425282:@Antonio Rinaldi]Prova con il terminale (shell)
openssl smime -verify -noverify -in documento.estensione.p7m -inform DER -out documento.estensione
dove documento.estensione è la tua fattura (comprensiva di percorso)[/quote]
Grande! Questo è molto di aiuto…
Mi resta ancora un intoppo con una sola fattura (fra le mille che ho testato) che sembra codificata base 64, ma ho comunque un errore di questo tipo… questa cosa mi sta facendo impazzire, sembra ci siano decine di standard diversi… una rabbia…

Error reading S/MIME message 4514993772:error:0DFFF0A8:asn1 encoding routines:CRYPTO_internal:wrong tag:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.240.1/libressl-2.6/crypto/asn1/tasn_dec.c:1125: 4514993772:error:0DFFF03A:asn1 encoding routines:CRYPTO_internal:nested asn1 error:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.240.1/libressl-2.6/crypto/asn1/tasn_dec.c:306:Type=PKCS7

Hai provato a fare la decodifica (da base64) e poi la conversione (come prima) del risultato?

Da quel che so dovrebbe funzionare, potresti fare una routine che in caso di errore del comando shell precedente provi il seguente:
base64 -d documento.estensione.p7m | openssl smime -verify -noverify -inform DER -out documento.estensione

Purtroppo non posso verificarlo, non avendo un file con questo tipo di problema a disposizione.

[quote=425498:@Antonio Rinaldi]Hai provato a fare la decodifica (da base64) e poi la conversione (come prima) del risultato?

Da quel che so dovrebbe funzionare, potresti fare una routine che in caso di errore del comando shell precedente provi il seguente:
base64 -d documento.estensione.p7m | openssl smime -verify -noverify -inform DER -out documento.estensione

Purtroppo non posso verificarlo, non avendo un file con questo tipo di problema a disposizione.[/quote]
Grazie mille Rinaldo! Preziosissimo! Sembra che la questione sia proprio questa… e in materia “riga di comando” sono davvero una capra… Grazie ancora!

scusa ma la fattura elettronica che arriva da PEC un messaggio con allegato un altro messaggio con gli allegati… non va decriptata…

Io mi riferisco ai files xml che arrivano… alcuni sono .p7m e alcuni di questi sono encodati… alcuni problemi li sto trovando andora onestamente…

Io devo leggere una Fattura Elettronica ( estensione xml ) firmata in XadES.

In pratica il blocco della firma alla fine dell’xml e facilmente eliminabile,
per alcuni tag sono stati modificati con l’aggiunta di attributi non presenti inizialmente, esempio:

<DatiAnagrafici>

stato modificato in:

<DatiAnagrafici xmlns:p="...." xmlns:xsi="...">

Openssl pu estrarre l’xml “pultito” come per i file .p7m ?

[quote=426094:@Paolo Boccolacci]Io devo leggere una Fattura Elettronica ( estensione xml ) firmata in XadES.

In pratica il blocco della firma è alla fine dell’xml e facilmente eliminabile,
però alcuni tag sono stati modificati con l’aggiunta di attributi non presenti inizialmente, esempio:

<DatiAnagrafici>

è stato modificato in:

<DatiAnagrafici xmlns:p="...." xmlns:xsi="...">

Openssl può estrarre l’xml “pultito” come per i file .p7m ?[/quote]
Non credo ma è ininfluente… con le funzioni xml di xojo puoi cercare il nodo DatiAnagrafici e ne leggi i contenuti… almeno se ho capito la tua domanda…

Probabilmente sbaglio nel costrure la stringa per la query in XmlNodeList=xmlDoc.XQL

come ho detto, alcuni nodi presentano dei tag modificati, e anche se riesco ad eliminare tutto
il blocco della firma, se nella query scrivo:

XmlNodeList=xmlDoc.XQL( "//FatturaElettronicaBody//DatiGenerali//DatiGeneraliDocumento//TipoDocumento/text()" )

Non mi restituisce nulla in quanto i primi due tag ( modificati con l’inserimento dell’elemento xmlns=… ) sono:

[code]

[/code]

cancellando la parte aggiunta ovvero facendo diventare i tag in questo modo:

<FatturaElettronicaBody> <DatiGenerali>

il relativo dato viene recuperato.

[quote=426104:@Paolo Boccolacci]Probabilmente sbaglio nel costrure la stringa per la query in XmlNodeList=xmlDoc.XQL

come ho detto, alcuni nodi presentano dei tag modificati, e anche se riesco ad eliminare tutto
il blocco della firma, se nella query scrivo:

XmlNodeList=xmlDoc.XQL( "//FatturaElettronicaBody//DatiGenerali//DatiGeneraliDocumento//TipoDocumento/text()" )

Non mi restituisce nulla in quanto i primi due tag ( modificati con l’inserimento dell’elemento xmlns=… ) sono:

[code]

[/code]

cancellando la parte aggiunta ovvero facendo diventare i tag in questo modo:

<FatturaElettronicaBody> <DatiGenerali>

il relativo dato viene recuperato.[/quote]
Nella mia ignoranza sto litigando parecchio su questa cosa… ammetto di essere, specialmente in ambito “xml”, una capra… Io sto risolvendo così (oltre alle varie idee che trovi già in questo thread):

  • leggo la stringa dell’xml con un textinputstream
  • eseguo una serie di controlli per rendere utilizzabile l’xml, partendo da (il problema che hai segnalato tu)
s=ReplaceAll(s," xmlns=""""","")
  • quindi, specialmente in caso di fatture firmate digitalmente, ho parecchio testo inutile sia prima che dopo i dati xml della stringa, e per trovare SOLO la stringa che mi interessa processare, eseguo qualcosa del genere

[code]inizio=InStrB(s,"<p:FatturaElettronica")-1
fine=InStrB(s,"</p:FatturaElettronica>")+LenB("</p:FatturaElettronica>")

if inizio<0 then
inizio=InStrB(s,"<P:FatturaElettronica")-1
fine=InStrB(s,"</P:FatturaElettronica>")+LenB("</P:FatturaElettronica>")
end if

if inizio<0 then
inizio=InStrB(s,"<FatturaElettronica")-1
fine=InStrB(s,"")+LenB("")
end if

if inizio<0 then
'<ns3:FatturaElettronica
inizio=InStrB(s,"<ns3:FatturaElettronica")-1
fine=InStrB(s,"</ns3:FatturaElettronica>")+LenB("</ns3:FatturaElettronica>")
end if

if inizio<0 then
'<ns2:FatturaElettronica - </ns2:FatturaElettronica>
inizio=InStrB(s,"<ns2:FatturaElettronica")-1
fine=InStrB(s,"</ns2:FatturaElettronica>")+LenB("</ns2:FatturaElettronica>")
end if[/code]
(sono le varianti che ho trovato fino ad ora)

  • quindi metto tutto nella stringa “s” da processare

s=MidB(s,inizio,fine-inizio) s="<?xml version=""1.0"" encoding=""utf-8""?>"+s

-e infine mando tutto al motore xml di xojo, in modo da poterlo lavorare

XMLDoc.LoadXml(s)

Come poi vado a processare la stringa, lo leggi qui sopra…

In realt, a parte il nodo iniziale, i name space all’interno non dovrebbero preoccuparvi (in quanto fuori dalla definizione del documento, a meno che non vogliate proprio questi campi non standard)
Per cui caricate normalmente il documento (nella forma leggibile ovvero non base64) e partite sempre nelle ricerche dei valori dal documentElement (in questo modo pu chiamarsi FatturaElettronica, o p:FatturaElettronica o ns2:FatturaElettronica o ns3:FatturaElettronica) voi andate nella parte interna della struttura.

quindi qualcosa come:
myXmlNodeList=xmlDoc.DocumentElement.XQL(“FatturaElettronicaBody/DatiGenerali/DatiGeneraliDocumento/TipoDocumento/text()” )

A meno di situazioni particolari dovreste sempre trovare il risultato cercato

due note:
non necessario dividere con // i rami, basta /
Partendo da DocumentElement la stringa di ricerca non deve partire con /, basta il nome dell’elemento da cui partire.
La sintassi proposta (// e // prima del primo nodo) ha significati diversi e in questo caso fuorvianti, meno efficienti e quindi per i vostri scopi inutili.

[quote=426122:@Antonio Rinaldi]In realtà, a parte il nodo iniziale, i name space all’interno non dovrebbero preoccuparvi (in quanto fuori dalla definizione del documento, a meno che non vogliate proprio questi campi non standard)
Per cui caricate normalmente il documento (nella forma leggibile ovvero non base64) e partite sempre nelle ricerche dei valori dal documentElement (in questo modo può chiamarsi FatturaElettronica, o p:FatturaElettronica o ns2:FatturaElettronica o ns3:FatturaElettronica) voi andate nella parte interna della struttura.

quindi qualcosa come:
myXmlNodeList=xmlDoc.DocumentElement.XQL(“FatturaElettronicaBody/DatiGenerali/DatiGeneraliDocumento/TipoDocumento/text()” )

A meno di situazioni particolari dovreste sempre trovare il risultato cercato

due note:
non è necessario dividere con // i rami, basta /
Partendo da DocumentElement la stringa di ricerca non deve partire con /, basta il nome dell’elemento da cui partire.
La sintassi proposta (// e // prima del primo nodo) ha significati diversi e in questo caso fuorvianti, meno efficienti e quindi per i vostri scopi inutili.[/quote]

Non è un problema di // o / ( nel mio caso ), le seguenti istruzioni:

[code]myXmlNodeList=xmlDoc.DocumentElement.XQL("/FatturaElettronicaBody/DatiGenerali/DatiGeneraliDocumento/TipoDocumento/text()" )

myXmlNodeList=xmlDoc.DocumentElement.XQL("//FatturaElettronicaBody//DatiGenerali//DatiGeneraliDocumento//TipoDocumento//text()" )

myXmlNodeList=xmlDoc.XQL("/FatturaElettronicaBody/DatiGenerali/DatiGeneraliDocumento/TipoDocumento/text()" )

myXmlNodeList=xmlDoc…XQL("/FatturaElettronicaBody//DatiGenerali//DatiGeneraliDocumento//TipoDocumento//text()" )[/code]

trovano l’elemento desiderato solo se i tag sono “puliti” ovvero se non sono stati modificati con l’attributo xmlns, esempio:

[code]

[/code]

Ma hai provato con FatturaElettronicaBody/DatiGenerali/DatiGeneraliDocumento/TipoDocumento/text(), senza il / all’inizio e partendo da documentElement?

Gli attributi di namespace non inficiano la ricerca nell’albero a meno che tu non stia cercando un nodo di un namespace (p:FatturaElettronica ad esempio)
visto che generalmente questo viene “modificato” solo a livello di nodo root nei nodi seguenti non dovresti aver problemi.

[quote=426219:@Antonio Rinaldi]Ma hai provato con FatturaElettronicaBody/DatiGenerali/DatiGeneraliDocumento/TipoDocumento/text(), senza il / all’inizio e partendo da documentElement?

Gli attributi di namespace non inficiano la ricerca nell’albero a meno che tu non stia cercando un nodo di un namespace (p:FatturaElettronica ad esempio)
visto che generalmente questo viene “modificato” solo a livello di nodo root nei nodi seguenti non dovresti aver problemi.[/quote]

Si, ho provato anche senza il / all’inizio, ma nulla.

In pratica io ho una cartella con vari file: xml firmati, xml non firmati, file p7m, tutti tranne questo tipo di xml firmati ( XadES ) non vengono letti in quanto in alcuni tag ci sono inseriti i dati che indico di seguito, se cancello i dati inseriti, i file si leggono.

Dati presenti ( xmlns=… ) solo in alcuni tag :

[code]

… [/code]

ed altri tag, ma non tutti.

Ho scritto male, i file nella cartella vengono tutti letti correttamente tranne i file xml firmati in XadES che presentanto alcuni tag modificati con l’aggiunta dell’elemento xmlns=…

Nel caso di Paolo (ovvero xmlns="") bisogna usare:
myXmlNodeList=xmlDoc.DocumentElement.XQL(“FatturaElettronicaBody/DatiGenerali/DatiGeneraliDocumento/TipoDocumento/text()”, array("", “”))

[quote=426346:@Antonio Rinaldi]Nel caso di Paolo (ovvero xmlns="") bisogna usare:
myXmlNodeList=xmlDoc.DocumentElement.XQL(“FatturaElettronicaBody/DatiGenerali/DatiGeneraliDocumento/TipoDocumento/text()”, array("", “”))[/quote]

Mitico Antonio !!! Grazie.

A questo punto l’ideale è fare una procedura che vada bene per tutte le casistiche, oppure, come fa Sergio, prendere il file, “ripulirlo” e processarlo.

Suggerimenti ?

Basta fare una variante delle funzione che avevo proposto per leggere direttamente il valore di un nodo.
si pu fare anche automatica vedendo se esiste un attributo xmlns e leggendone il valore e creando l’array di conseguenza.

Mi capitano ancora cose strane, in circa il 2% dei casi, per ho alcune letture di fatture xml che falliscono. Ecco tre screen emblematici:


Secondo voi come posso ovviare, sapendo che quando vado a leggere la stringa dell’xml converto la codifica a utf8

t=TextInputStream.Open(xmlFile) s=t.ReadAll(Encodings.UTF8) s=ReplaceLineEndings(s,EndOfLine.Windows) s=ReplaceAll(s," xmlns=""""","")

(l’ultima riga pu essere di aiuto per quello che dicevano @AntonioRinaldi e @PaoloBoccolacci )

Certo che questa cosa della lettura delle fatture xml pi complicata del previsto per via di alcuni software di generazione che (a mio avviso) non rispettano al 100% lo standard della fattura…