Oppure

Loading
26/06/21 15:32
bernie

Riesumo questo mio vecchio post, spero di non aver infranto qualche regolamento .
Inizio col postare il programma
Dim nuovo As New Xml.XmlDocument()
        nuovo.Load("C:\Digitalframe\XUSB.xml")
        Dim xmlnuovo As Xml.XmlNodeList = nuovo.ChildNodes(1).ChildNodes
        xmlnuovo.Item(2).InnerText = "pippo"
        nuovo.Save(" C:\Digitalframe\XUSB5.xml")


Ho un file XML non scritto da me , di cui avrei bisogno di modificare determinati campi .
Ogni nodo ha dei nodi figli , io devo andare a modificare i nodi figli .
Il codice che ho scritto , mi va a modificare il nodo eliminando tutti i nodi figli .

<HeadOffsetRegisters>
<PaletteRemap0 type="integer" value="0" />
<PaletteRemap1 type="integer" value="7" />
<PaletteRemap2 type="integer" value="7" />
<PaletteRemap3 type="integer" value="7" />
<PaletteRemap4 type="integer" value="7" />
<PaletteRemap5 type="integer" value="7" />
<PaletteRemap6 type="integer" value="7" />
<PaletteRemap7 type="integer" value="7" />

Io devo modificare il valore di value.

Allego anche il file XML completo
Grazie
aaa
26/06/21 21:05
Carlo
Non ho mai imparato ad usare XmlDocuments o HtmlDocuments, perché ogni volta che ho iniziato, poi avevo delle incompatibilità, XML troppo vecchi o troppo nuovi, oppure dialetti dedicati... Se nessuno ci illumina con un esempio, partendo dal tuo Xml, un grazie anticipato :rotfl:

Però non mi sono mai scoraggiato, un Xml è un file testo e trattandolo come tale si possono fare tutte le operazioni pensabili.
Ho scritto due righe. Su un nuovo progetto winform aggiungi un bottone ed una textbox:

Imports System.IO

Public Class Form1
    Dim XML As String
    Dim pos1 As Integer
    Dim pos2 As Integer
    Dim NodoOUT As String

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        TextBox1.Multiline = True
        TextBox1.WordWrap = False
        XML = File.ReadAllText("XUSB.XML")
        Dim NodoIN As String = "<HeadOffsetRegisters>"
        NodoOUT = "</HeadOffsetRegisters>"
        pos1 = XML.IndexOf(NodoIN)
        pos2 = XML.IndexOf(NodoOUT)
        TextBox1.Text = XML.Substring(pos1, pos2 - pos1 + NodoOUT.Length)
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim XMLout As String = XML.Substring(0, pos1)
        XMLout += TextBox1.Text
        XMLout += XML.Substring(pos2 + NodoOUT.Length)
        File.WriteAllText("XUSBmod.XML", XMLout)
    End Sub
End Class


Il programma apre il file: XUSB.XML, che deve esistere nella stessa cartella dell'eseguibile.
Individua i nodi e ne mostra il contenuto, ora nella textbox puoi modificare quello che vuoi, anche aggiungere o togliere una riga PletteRemap.
Cliccando il Button, un nuovo file viene salvato di nome: XUSBmod.XML, sempre nella cartella che contiene l'eseguibile.

Partendo da questo esempio, puoi ampliarlo per ottenere una serie di textbox dove modificare i valori, magari controllando anche la validità dell'input, automatizzare prendendo i valori da dove vuoi, aggiungere una ShowOpen e una ShowSave ecc ecc.

Credo che se anche sapessi padroneggiare XmlDocuments e XmlNode, per una modifica così semplice non li userei.
Ultima modifica effettuata da Carlo 26/06/21 21:15
in programmazione tutto è permesso
27/06/21 8:44
bernie
Ciao Carlo
Grazie per l'esempio che funziona modificando i dati dalla textbox.
Come avevi intuito io devo modificare i dati in automatico , e non manualmente .
Avevo quindi pensato una soluzione del genere , ma mi da un errore e non capisco perchè.

Ho prima provato il tuo esempio per vedere se il file modificato era riconosciuto e fino qui tutto ok .
Ho poi pensato di modificare i vari campi che devo modificare, e forse qui mi sono complicato la vita , ma mi sembra la soluzione più logica. Ho caricato la parte del file che veniva visualizzato nella textbox in una variabile stringa( testo1), ho poi creato un xml e l'ho popolato con testo1. A questo punto ho cercato di modificare i vari nodi , ma mi compare l'errore qui di sotto . Evidenziata la riga riportata

System.NullReferenceException: 'Riferimento a un oggetto non impostato su un'istanza di oggetto.'
Dim xmlElem As Xml.XmlNodeList = xmlFile.ChildNodes(1).ChildNodes

Allego la parte di listato che ho modificato .
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim XMLout As String = XML.Substring(0, pos1)
        Dim testo1 As String
        Dim xmlFile As New Xml.XmlDocument()


        testo1 = XML.Substring(pos1, pos2 - pos1 + NodoOUT.Length)

        xmlFile.LoadXml(testo1)

        Dim xmlElem As Xml.XmlNodeList = xmlFile.ChildNodes(1).ChildNodes

        xmlElem.Item(0).InnerText = "0"
        xmlElem.Item(1).InnerText = "9"
        xmlElem.Item(2).InnerText = "8"
        xmlElem.Item(3).InnerText = "7"
        xmlElem.Item(4).InnerText = "6"
        xmlElem.Item(5).InnerText = "5"
        xmlElem.Item(6).InnerText = "4"
        xmlElem.Item(7).InnerText = "3"
        XMLout += (xmlFile.InnerXml)
        XMLout += XML.Substring(pos2 + NodoOUT.Length)
        File.WriteAllText("C:\DigitalFrame\XUSB2.XML", XMLout)
    End Sub

Grazie
aaa
27/06/21 20:27
Carlo
Come ti avevo detto, non ho dimestichezza con le istruzioni dedicate, perchè, se si padroneggia la manipolazione delle stringhe le istruzioni dedicate sono inutili per compiti semplici, il discorso cambia con HTML o XML complessi, ma ad oggi non ne ho mai sentito la necessità.

Restando nell'ambito della manipolazione delle stringhe hai due possibilità, una adatta se il nodo ha un'impostazione fissa, cioè il valore da cambiare si trova sempre nella stessa posizione nel nodo, la seconda è andare a caccia della posizione del valore da cambiare con IndexOf, usando lo stesso metodo che ho usato per trovare: HeadOffsetRegisters.

Nel primo esempio ti mostro come fare presumendo che i valori da cambiare si trovino sempre nella stessa posizione nel nodo, ho aggiunto tre buttons che simulano l'automazione:
Imports System.IO

Public Class Form1
    Dim XML As String
    Dim pos1 As Integer
    Dim pos2 As Integer
    Dim NodoOUT As String

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        TextBox1.Multiline = True
        TextBox1.WordWrap = False
        XML = File.ReadAllText("XUSB.XML")
        Dim NodoIN As String = "<HeadOffsetRegisters>"
        NodoOUT = "</HeadOffsetRegisters>"
        pos1 = XML.IndexOf(NodoIN)
        pos2 = XML.IndexOf(NodoOUT)
        TextBox1.Text = XML.Substring(pos1, pos2 - pos1 + NodoOUT.Length)
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim XMLout As String = XML.Substring(0, pos1)
        XMLout += TextBox1.Text
        XMLout += XML.Substring(pos2 + NodoOUT.Length)
        File.WriteAllText("XUSBmod.XML", XMLout)
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        ' modifica PaletteRemap0
        Dim NuovoValore0 = 8
        TextBox1.Text = TextBox1.Text.Remove(68, 1).Insert(68, NuovoValore0)
    End Sub

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        ' modifica PaletteRemap1
        Dim NuovoValore1 = 5
        TextBox1.Text = TextBox1.Text.Remove(120, 1).Insert(120, NuovoValore1)
    End Sub

    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        ' modifica PaletteRemap2
        Dim NuovoValore2 = 6
        TextBox1.Text = TextBox1.Text.Remove(172, 1).Insert(172, NuovoValore2)
    End Sub
End Class


Ho modificato il valore nella TextBox, così vedi il risultato immediato, ma se usi: testo1 il codice non cambia.



Nel secondo esempio accedo direttamente al valore da modificare:
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim NuovoValore0 = 1 ' Valore che si vuole assegnare a PaletteRemap0
        Dim NuovoValore1 = 2 ' Valore che si vuole assegnare a PaletteRemap1
        Dim NuovoValore2 = 3 ' Valore che si vuole assegnare a PaletteRemap2
        XML = File.ReadAllText("XUSB.XML") ' carico il file

        Dim pos = XML.IndexOf("<PaletteRemap0") ' indice del nome
        XML = XML.Remove(pos + 37, 1).Insert(pos + 37, NuovoValore0) ' sostituzione vecchio valore con il nuovo

        pos = XML.IndexOf("<PaletteRemap1") ' indice del nome
        XML = XML.Remove(pos + 37, 1).Insert(pos + 37, NuovoValore1) ' sostituzione vecchio valore con il nuovo

        pos = XML.IndexOf("<PaletteRemap2") ' indice del nome
        XML = XML.Remove(pos + 37, 1).Insert(pos + 37, NuovoValore2) ' sostituzione vecchio valore con il nuovo

        File.WriteAllText("XUSBmod.XML", XML) ' scrittura XML con i valori di PaletteRemap0/1/2 modificati
End Sub


Se il valore di PaletteRemap può avere anche due o più cifre, bisogna aggiungere una riga che ne riconosca il numero delle cifre e su remove, invece di 1, bisogna mettere il numero delle cifre trovate.

Resto sempre dell'avviso che mi piacerebbe vedere come fare la stessa cosa con XmlDocuments, XmlNode, XmlNodeList e ChildNodes.
Ultima modifica effettuata da Carlo 27/06/21 22:19
in programmazione tutto è permesso
28/06/21 4:02
bernie
Buon giorno Carlo
Questa sera vedo di provare i due esempi.
Sinceramente il secondo esempio è quello che hai tentato di fare senza successo.
Appena li provo ti faccio sapere.
Grazie e buona giornata.
aaa
28/06/21 20:17
bernie
Ciao Carlo
prima di tutto vorrei scusarmi , questa mattina ho scritto il messaggio in fretta e non mi sono reso conto che il correttore ha cambiato una parola "Sinceramente il secondo esempio è quello che hai tentato di fare senza successo", io non ero riuscito a farlo , tu ci sei riuscito benissimo , scusa e grazie .

Ho modificato il tuo secondo esempio e adesso mi piace
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        Dim NuovoValore = 7                                             ' nuovo valore 
        Dim indice As Integer = 1
        Dim testo As String

        While indice <= 7
            XML = File.ReadAllText(" C:\Digitalframe\XUSB.xml")         ' carico il file
            testo = "<PaletteRemap" & indice                            ' compongo l'indice del nome 
            Dim pos = XML.IndexOf(testo)                                ' indice del nome
            XML = XML.Remove(pos + 37, 1).Insert(pos + 37, NuovoValore) ' sostituzione vecchio valore con il nuovo
            File.WriteAllText("C:\Digitalframe\XUSB.xml", XML)          ' scrittura XML con i valori di PaletteRemap modificati
            indice += 1
        End While

    End Sub

Devo riscrivere ogni volta lo stesso file, altrimenti mi ritrovo che ha modificato solo l'ultima voce . Ma questo non è un problema , anzi, a pensarci deve essere cosi .

Ogni suggerimento è ben accetto .
Grazie di nuovo
aaa
28/06/21 20:42
Carlo
Bravo, ma si può evitare di scrivere e leggere 8 volte il file per scrivere tutti sette:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        XML = File.ReadAllText("C:\Digitalframe\XUSB.xml") ' carico il file
        Dim pos As Integer = 0 ' lo uso anche come startindex, ricerca in sequenza
        For p = 0 To 7
            pos = XML.IndexOf("<PaletteRemap" & p.ToString, pos) ' indice del nome progressivo
            XML = XML.Remove(pos + 37, 1).Insert(pos + 37, 7.ToString) ' sostituzione con 7
        Next
        File.WriteAllText("C:\Digitalframe\XUSB.xml", XML)
End Sub
Ultima modifica effettuata da Carlo 28/06/21 22:10
in programmazione tutto è permesso
28/06/21 21:25
bernie
In realtà, il primo deve sempre essere a 0. Gli altri 7 possono variare da 1 a 7.
Non l'ho capito bene, domani dal PC me lo studio. Se pos lo setto a 1 e il ciclo for lo inizio da 1, dovrei essere a posto.
Grazie Carlo, domani me lo studio.
aaa