Lettura Xml Nodo inesistente.

di il
6 risposte

Lettura Xml Nodo inesistente.

Salve,
Dopo varie ricerche non sono riuscito a trovare una soluzione al mio problema.
Devo estrarre dei dati da un file XML utilizzando DOM la funzione che uso è questa:
Public Function ImportaRigheAnno() 'Massivo Anno
Dim StartPath As String, NomeFile, FullPath As String, strsql As String, MyAnno As Integer, NrLinea As Integer, i As Integer
Dim db As DAO.Database
Dim rs1 As DAO.Recordset, rs2 As DAO.Recordset
MyAnno = DLookup("Esercizio", "TbAvvio")
On Error GoTo GestErr
  'seleziona la riga unica Lato 1
    strsql = "SELECT IdPrimaNota, IdSezione, AnnoF, NomeFile " & _
                "FROM TbPrimaNota " & _
                "WHERE TbPrimaNota.AnnoF=" & MyAnno & "and IdSezione=" & 1
   
    Set rs1 = CurrentDb.OpenRecordset(strsql)
         rs1.MoveFirst
         Do Until rs1.EOF

NomeFile = (rs1!NomeFile) 'Prelevo dalla tabella il nome del file da elaborare
StartPath = Application.CurrentProject.Path & "\XML\FattureFornitoriArchiviate\"  
'Prelevo dalla tabella il percorso del file da elaborare
FullPath = StartPath & NomeFile 'Compongo il percorso completo

'INIZIO LETTURA FILE XML  ## dati di righe solo i Dieci nodi
Dim obj As DOMDocument
Dim Verifica As Boolean
Dim Nodo As IXMLDOMNodeList
Dim Nome As IXMLDOMNode

'ACCESSO AL FILE XML
     Set obj = New DOMDocument
     obj.async = False
     obj.Load (FullPath)
Set rs2 = CurrentDb.OpenRecordset("TbFileRigheFattForn", dbOpenDynaset) 'Recordset per popolare il Lato Molti
 'Conto quanti nodi ha DettaglioLinee
    NrLinea = obj.getElementsByTagName("DatiBeniServizi/DettaglioLinee/NumeroLinea").length

'Inizio ciclo per DatiBeniServizi (estraggo child Nodi per popolare il lato molti
   Do While i < NrLinea
       rs2.AddNew
      rs2.Fields("IdPrimaNota") = (rs1!IdPrimaNota)
 rs2.Fields("Descrizione") = Trim(obj.documentElement.selectNodes("//DatiBeniServizi/DettaglioLinee/Descrizione").Item(i).Text)
 rs2.Fields("CodiceArticolo") = Trim(obj.documentElement.selectNodes("//DatiBeniServizi/DettaglioLinee/CodiceArticolo").Item(i).Text)
   rs2.Update
    i = i + 1
    DoEvents
    Loop

'CHIUDO IL FILE
Set obj = Nothing
rs1.MoveNext
Loop
'  Chiusura e distruzione recordset
rs1.Close
Set rs1 = Nothing
rs2.Close
Set rs2 = Nothing
MsgBox "Righe Estratte!", vbInformation

Exit Function  '>>>>>>>>>>>>>>>>>>>>>>>>necessario per eliminare errore ZERO
GestErr:
    Select Case Err.Number
               Case 91  ' Il nodo non esiste
                       'MsgBox "Valore NON Ammesso !" & vbNewLine & vbNewLine & " Digita un numero VALIDO !", vbExclamation, "Calcolatrice"
                      Resume Next 'Dato_KeyDown_exit
               Case Err.Number <> 0
                      MsgBox "Errore N° " & Err.Number & vbNewLine & Err.Description
                      Resume Next
End Select
GoTo Fine:
Fine:

End Function
Tutto va bene se il nodo (ne ho inserito solo 2 per semplificare) è esistente va tutto bene se invece questo è inesistente da un errore del blocco ...etc
Ho cercato di risolvere con la gestione degli errori ma se un nodo non esiste salta l'intero documento.
NB il Nodo nell'xml non è "Non valorizzato" ma la riga non esiste affatto, infatti se commento la riga del nodo assente tutti gli altri vengono estratti regolarmente.
Qualcuno ha una soluzione da suggerirmi, grazie anticipate.
Gianni

6 Risposte

  • Re: Lettura Xml Nodo inesistente.

    Gianni55 ha scritto:


    Devo estrarre dei dati da un file XML utilizzando DOM la funzione che uso è questa: [...]
    NrLinea = obj.getElementsByTagName("DatiBeniServizi/DettaglioLinee/NumeroLinea").length
    Tutto va bene se il nodo (ne ho inserito solo 2 per semplificare) è esistente va tutto bene se invece questo è inesistente da un errore del blocco ...etc
    Credo che tu debba modificare il modo in cui leggi i nodi, iterando gli elementi ed evitando di usare il numero di riga, o comunque l'approccio che hai adottato complica parecchio il codice da scrivere.

    Potresti invece strutturarlo in questo modo:
    
        Set obj = New DOMDocument
        
        Set dettaglioLinee = obj.DocumentElement.SelectNodes("//DatiBeniServizi/DettaglioLinee")
        
        For Each lineaDettaglio In dettaglioLinee
            Set descrizioneArticolo = lineaDettaglio.SelectSingleNode("./Descrizione")
            Set codiceArticolo = lineaDettaglio.SelectSingleNode("./CodiceArticolo")
            ' ...
        Next
    
    In pratica, invece di scandire direttamente gli elementi finali (senza riuscire a determinare con precisione quali sono), devi invece scandire quelli superiori che si ripetono e, quando presenti, per ciascuno, accede ai sottoelementi ed estrarre singolarmente le informazioni che ti interessano, usando nel modo corretto i metodi SelectNodes() e SelectSingleNode() a seconda dei casi e indicando l'espressione XPath corretta.

    P.S.: non ho verificato il codice sopra all'interno dell'editor, quindi prendilo come spunto di riflessione (pseudocodice).

    Ciao!
  • Re: Lettura Xml Nodo inesistente.

    Salve Alka
    intanto grazie per il suggerimento proverò a modificare il mio codice e ti faccio sapere.
    Saluti
  • Re: Lettura Xml Nodo inesistente.

    Rieccomi
    Ho modificato il codice, spero, come suggerito da AIKA:
    Public Function ImportaRigheAnno() 'Massivo Anno
    Dim StartPath As String, NomeFile, FullPath As String, strsql As String, MyAnno As Integer, NrLinee As Integer, i As Integer, Testo As String
    Dim db As DAO.Database
    Dim rs1 As DAO.Recordset, rs2 As DAO.Recordset
    MyAnno = DLookup("Esercizio", "TbAvvio")
    On Error Resume Next
    'On Error GoTo GestErr
      'seleziona la riga unica Lato 1
        DBEngine(0)(0).Execute "Delete TbFileRigheFattForn.IdPrimaNota FROM TbFileRigheFattForn;"
        strsql = "SELECT IdPrimaNota, IdSezione, AnnoF, NomeFile " & _
                 "FROM TbPrimaNota " & _
                 "WHERE TbPrimaNota.AnnoF=" & MyAnno & "and IdSezione=" & 1
       
        Set rs1 = CurrentDb.OpenRecordset(strsql)
        
         rs1.MoveFirst
     Do Until rs1.EOF
    
    NomeFile = (rs1!NomeFile) 'Prelevo dalla tabella il nome del file da elaborare
    StartPath = Application.CurrentProject.Path & "\XML\FattureFornitoriArchiviate\"  'Prelevo dalla tabella il percorso del file da elaborare
    FullPath = StartPath & NomeFile 'Compongo il percorso completo
    'Debug.Print FullPath
    '==========================================================================================
    'INIZIO LETTURA FILE XML  ## dati di righe solo i Dieci nodi
    '==========================================================================================
    Dim obj As DOMDocument
    Dim Verifica As Boolean
    Dim Nodo As IXMLDOMNodeList
    Dim Nome As IXMLDOMNode
    Dim dettaglioLinee As IXMLDOMNodeList
    Dim lineaDettaglio As IXMLDOMNode
    Dim NumeroLinea As IXMLDOMNode, CodiceArticolo As IXMLDOMNode, Descrizione As IXMLDOMNode, Quantita As IXMLDOMNode, UnitaMisura As IXMLDOMNode
    Dim PrezzoUnitario As IXMLDOMNode, ScontoMaggiorazione As IXMLDOMNode, PrezzoTotale As IXMLDOMNode, AliquotaIva As IXMLDOMNode
    
    '==========================================================================================
    'ACCESSO AL FILE XML
    '==========================================================================================
    Set obj = New DOMDocument
    obj.async = False
    obj.Load (FullPath)
    
     
        
        
        Set dettaglioLinee = obj.documentElement.selectNodes("//DatiBeniServizi/DettaglioLinee")
     
        
         For Each lineaDettaglio In dettaglioLinee
             Set NumeroLinea = NumeroLinea.selectSingleNode("./NumeroLinea")
         Debug.Print NumeroLinea.Text
            Set CodiceArticolo = lineaDettaglio.selectSingleNode("./CodiceArticolo")
          Debug.Print CodiceArticolo.Text
            Set Descrizione = lineaDettaglio.selectSingleNode("./Descrizione")
           Debug.Print Descrizione.Text
             Set Quantita = lineaDettaglio.selectSingleNode("./Quantita")
          Debug.Print Quantita.Text
            Set UnitaMisura = lineaDettaglio.selectSingleNode("./UnitaMisura")
          Debug.Print UnitaMisura.Text
            Set PrezzoUnitario = lineaDettaglio.selectSingleNode("./PrezzoUnitario")
          Debug.Print PrezzoUnitario.Text
            Set ScontoMaggiorazione = lineaDettaglio.selectSingleNode("./ScontoMaggiorazione")
          Debug.Print ScontoMaggiorazione.Text
            Set PrezzoTotale = lineaDettaglio.selectSingleNode("./PrezzoTotale")
          Debug.Print PrezzoTotale.Text
            Set AliquotaIva = lineaDettaglio.selectSingleNode("./AliquotaIVA")
        Debug.Print AliquotaIva.Text
       Next
    Set obj = Nothing
    
          
          Set rs2 = CurrentDb.OpenRecordset("TbFileRigheFattForn", dbOpenDynaset) 'Recordset per popolare il Lato Molti
    
         
         With rs2
           .AddNew
              .Fields("IdPrimaNota") = (rs1!IdPrimaNota)
              .Fields("NumeroLinea") = Trim(NumeroLinea.Text)
              .Fields("CodiceArticolo") = Trim(CodiceArticolo.Text)
              .Fields("Descrizione") = Trim(Descrizione.Text)
              .Fields("Quantita") = Replace(Quantita.Text, ".", ",")
              .Fields("UnitaMisura") = Trim(UnitaMisura.Text)
              .Fields("PrezzoUnitario") = Replace(PrezzoUnitario.Text, ".", ",")
              .Fields("ScontoMaggiorazione") = Replace(ScontoMaggiorazione.Text, ".", ",")
              .Fields("PrezzoTotale") = Replace(PrezzoTotale.Text, ".", ",")
              .Fields("AliquotaIVA") = Replace(AliquotaIva.Text, ".", ",")
           .Update
           .MoveNext
          'DoEvents
        End With
      
    rs1.MoveNext
    'Debug.Print FullPath
    Loop
    '==========================================================================================
    '  Chiusura e distruzione recordset
    '==========================================================================================
    rs1.Close
    Set rs1 = Nothing
    rs2.Close
    Set rs2 = Nothing
    '==========================================================================================
    
    MsgBox "Righe Estratte!", vbInformation
    End Function
    Superato il problema che si creava: nel caso un nodo fosse assente il record non veniva estratto.

    Ora atteso che dal Lato 1 vi sono 26 documenti e che il lato molti contiene le righe che estraiamo dal xml in questione
    si verifica che le righe (da debug vengono estratti regolarmente -se nodo assente la riga viene estratta)
    mentre nel recordset della Tab di destinazione viene esportata solo la 1°Riga di tutti i 26 documenti.
    Sicuramente sto sbagliando qualcosa in questa parte di codice...ma in questo momento sono fuso e non riesco a capire dove stà l'errore:
     Set rs2 = CurrentDb.OpenRecordset("TbFileRigheFattForn", dbOpenDynaset) 'Recordset per popolare il Lato Molti
    
         
         With rs2
           .AddNew
              .Fields("IdPrimaNota") = (rs1!IdPrimaNota)
              .Fields("NumeroLinea") = Trim(NumeroLinea.Text)
              .Fields("CodiceArticolo") = Trim(CodiceArticolo.Text)
              .Fields("Descrizione") = Trim(Descrizione.Text)
              .Fields("Quantita") = Replace(Quantita.Text, ".", ",")
              .Fields("UnitaMisura") = Trim(UnitaMisura.Text)
              .Fields("PrezzoUnitario") = Replace(PrezzoUnitario.Text, ".", ",")
              .Fields("ScontoMaggiorazione") = Replace(ScontoMaggiorazione.Text, ".", ",")
              .Fields("PrezzoTotale") = Replace(PrezzoTotale.Text, ".", ",")
              .Fields("AliquotaIVA") = Replace(AliquotaIva.Text, ".", ",")
           .Update
           .MoveNext
          'DoEvents
        End With
      
    rs1.MoveNext
    'Debug.Print FullPath
    Loop
    '==========================================================================================
    '  Chiusura e distruzione recordset
    '==========================================================================================
    rs1.Close
    Set rs1 = Nothing
    rs2.Close
    Set rs2 = Nothing
    
    Qualcuno può aiutarmi? grazie anticipate

  • Re: Lettura Xml Nodo inesistente.

    Ciao, da una prima occhiata al tuo codice ti inserisce solo una riga perchè fai l'.AddNew fuori dal ciclo For Each lineaDettaglio In dettaglioLinee.
    Sposta il codice all'interno del For...Next e vedrai che va tutto bene

    Andrea
  • Re: Lettura Xml Nodo inesistente.

    VBAndre ha scritto:


    Ciao, da una prima occhiata al tuo codice ti inserisce solo una riga perchè fai l'.AddNew fuori dal ciclo For Each lineaDettaglio In dettaglioLinee.
    Sposta il codice all'interno del For...Next e vedrai che va tutto bene

    Andrea
    Ma roba da matti stavo rincretinendo da 2 giorni, non sapevo più che pesci pigliare, lo stavo mettendo a riposo per un paio di giorni di solito funziona.
    Grazie infinite Andrea
  • Re: Lettura Xml Nodo inesistente.


    figurati!
    va sempre così; spesso basterebbe uscire e riguardare il codice 2 giorni dopo con occhi nuovi e invece mi trovo spesso anch'io a sbatterci la testa
    Buona serata
Devi accedere o registrarti per scrivere nel forum
6 risposte