salve, ho usato la xml lib per salvare il contenuto di una treeview in xml... ma ora come faccio a scorrere gli elementi dell'xml??
ecco il mio xml generato:<?xml version="1.0" encoding="UTF8"?>
<slyproj>
<prognam>newproj</prognam>
<glvar>
<var type="string">varnam</var>
</glvar>
<func></func>
<main>
<cinput>a</cinput>
<if cond="(condition) then">
<cprint>a</cprint>
</if>
</main>
</slyproj>
Vedere per credere, eh?!?
Comunque, di seguito uno dei pezzi di codice contenuti in pgDesigner2, con cui leggo un file di configurazione. Ovviamente è legato alla struttura del file, per cui prova ad adattarlo alle tue esigenze. Tieni conto che pezzetti di codice simile sono sparsi per i vari e innumerevoli oggetti del mio programma:
STATIC PRIVATE $list AS Object[]
STATIC PUBLIC FUNCTION List() AS Object[]
DIM oXmlDocument AS pgXmlDocument
DIM oXmlRoot, oXmlElement AS pgXmlElement
DIM oXmlAttribute AS pgXmlAttribute
DIM info AS pgDriverInfo
IF (IsNull($list)) THEN
pgApplication.MessageInfo(ME, "Load drivers configuration")
$list = NEW Object[]
IF (NOT Exist(DRIVER_FILENAME)) THEN
Error.Raise(("Not driver list file present !"))
END IF
oXmlDocument = pgXmlDocument()
oXmlDocument.Load(DRIVER_FILENAME)
oXmlRoot = oXmlDocument.Root.Elements[0]
FOR EACH oXmlElement IN oXmlRoot.Elements
info = pgDriverInfo()
FOR EACH oXmlAttribute IN oXmlElement.Attributes
SELECT CASE String.Lower(oXmlAttribute.Name)
CASE "name"
info.Name = Str(oXmlAttribute.Value)
CASE "type"
info.Type = Str(oXmlAttribute.Value)
CASE "class"
info.Class = Str(oXmlAttribute.Value)
CASE "sql"
info.ImportSqlEnable = (String.Lower(oXmlAttribute.Value) = "true")
CASE "port"
info.Port = Str(oXmlAttribute.Value)
END SELECT
NEXT
IF (NOT IsNull(Trim(info.Name)) AND
NOT IsNull(Trim(info.Class)) AND
NOT IsNull(Trim(info.Type))) THEN
IF (pgDatabaseInfo.GetListTypes().Find(info.Type) = -1) THEN
pgApplication.MessageWarning(ME, ("Database type not valid!") & " [" & info.Type & "]")
ELSE
$list.Add(info)
pgApplication.MessageDebug(ME, "DriverInfo.Add(" & info.ToString() & ")")
END IF
END IF
NEXT
END IF
RETURN $list
END
Inoltre, tieni presente che, per esigenze interne al programma, i nomi delle classi potrebbero non essere uguali, ma non credo sia difficile distinguerli... :D
Leggi il codice nella precedente:
oXmlDocument = pgXmlDocument()
oXmlDocument.Load(DRIVER_FILENAME)
che tradotto in codice più semplice:
DIM oXmlDocument AS NEW XmlDocument
oXmlDocument.Load("nome del file")
Il seguito del codice ti dimostra come poi leggere i dati che la classe ha caricato.
E' necessario che tu interpreti l'esempio, in modo da capire i passi essenziali per usare la classe. Il codice che ti ho postato è un pezzo di codice operativo, che ha dei riferimenti che sono utili ma non interessano direttamente il tuo caso, per cui estrapola la parte interessante per te.
Il metodo "Load" ha solo il compito di leggere e scompattare il contenuto del file. Una volta che ha terminato la sua funzione, i dati scompattati sono contenuti nelle proprietà della classe.
Public Sub load_Click()
Dim $root As Element
Dim oRoot As Element
Dim oElement As Element
Dim oAttribute As Attribute
Dim oXml As New XmlReader
Dim enam As String
Dim cp As String
Dim sv As Integer
doc = New Document
Dialog.Title = "Open a Project"
Dialog.Filter = ["Sly Project (*.slyproj)"]
If Dialog.OpenFile() Then Return
SetPath(Dialog.Path)
iab = 4
tvcode.Clear()
$root = New Element(Null, Null, Null)
$root.Name = "root"
$root.Elements.Clear()
$root.Attributes.Clear()
oRoot = $root
oXml.Open($sPath)
Do Until (oXml.Eof)
Select Case oXml.Node.Type
Case XmlReaderNodeType.Element
'Message.Info(oXml.Node.Name)
Select Case oXml.Node.Name
Case "glvar"
tvcode.Add("1", "global variables", vars)
cp = "1"
Case "func"
tvcode.Add("2", "functions", func)
cp = "2"
Case "main"
tvcode.Add("3", "main", main)
cp = "3"
Default
If oXml.Node.Name <> "slyproj" And oXml.Node.Name <> "prognam" Then
tvcode.Add(iab, oXml.Node.Name, act, cp).EnsureVisible
tvcode.Item.EnsureVisible
cp = iab
iab = iab + 1
Endif
End Select
enam = oXml.Node.Name
oElement = New Element(oRoot, oXml.Node.Name, oXml.Node.Value)
For Each oXml.Node.Attributes
oAttribute = New Attribute(oElement, oXml.Node.Name, oXml.Node.Value)
oElement.Attributes.Add(oAttribute)
Next
oRoot.Elements.Add(oElement)
oRoot = oElement
Case XmlReaderNodeType.EndElement
oRoot = oRoot.Parent
If enam <> "slyproj" And enam <> "prognam" And enam <> "glvar" And enam <> "functions" And enam <> "main" Then
cp = tvcode.Item.ParentKey
sv = CInteger(cp) 'ERRORE
sv = sv - 1
cp = CString(sv)
Endif
Case XmlReaderNodeType.Text
oElement.Value &= Trim(oXml.Node.Value)
'Message.Info(oXml.Node.Value)
If enam <> "slyproj" And enam <> "prognam" Then
tvcode.Add(CString(iab), enam & " " & oXml.Node.Value, cond, cp).EnsureVisible
tvcode.Item.EnsureVisible
iab = iab + 1
Else If enam = "prognam" Then
progname = oXml.Node.Value
Endif
End Select
oXml.Read()
Loop
oXml.Close()
End
se non mi dasse errore andrebbe! mi dice type mysmatch wanted integer got string (dove ho fatto il commento errore)
Ma, hai provato a metterti in debug e analizzare i dati della linea?
sv = CInteger(cp) 'ERRORE
Presumo che la variabile "tvcode" sia una TreeList, per cui prova ad analizzare cosa c'è in questo oggetto.
L'errore non è dipeso direttamente dalla libreria XML, ma è il caso di capire se:
1 - la struttura del file viene letta e decodificata correttamente
2 - i valori che utilizzi sono sempre validi (non null)
3 - la Tree venga popolata correttamente, con tutti i corretti riferimenti (es. la ParentKey)
Dim $root As Element
Dim oRoot As Element
Dim oElement As Element
Dim oAttribute As Attribute
Dim oXml As New XmlReader
Dim enam As String
Dim cp As Variant
Dim sv As Variant
doc = New Document
Dialog.Title = "Open a Project"
Dialog.Filter = ["Sly Project (*.slyproj)"]
If Dialog.OpenFile() Then Return
SetPath(Dialog.Path)
iab = 4
tvcode.Clear()
$root = New Element(Null, Null, Null)
$root.Name = "root"
$root.Elements.Clear()
$root.Attributes.Clear()
oRoot = $root
oXml.Open($sPath)
Do Until (oXml.Eof)
Select Case oXml.Node.Type
Case XmlReaderNodeType.Element
'Message.Info(oXml.Node.Name)
Select Case oXml.Node.Name
Case "glvar"
tvcode.Add("1", "global variables", vars)
cp = "1"
Case "func"
tvcode.Add("2", "functions", func)
cp = "2"
Case "main"
tvcode.Add("3", "main", main)
cp = "3"
Default
If oXml.Node.Name <> "slyproj" And oXml.Node.Name <> "prognam" And oXml.Node.Name <> "cprint" And oXml.Node.Name <> "cinput" Then
tvcode.Add(iab, oXml.Node.Name, act, cp).EnsureVisible
tvcode.Item.EnsureVisible
ablocks[iab] = New Block
ablocks[iab].tp = oXml.Node.Name
ablocks[iab].father = True
cp = iab
iab = iab + 1
Endif
End Select
enam = oXml.Node.Name
oElement = New Element(oRoot, oXml.Node.Name, oXml.Node.Value)
For Each oXml.Node.Attributes
oAttribute = New Attribute(oElement, oXml.Node.Name, oXml.Node.Value)
oElement.Attributes.Add(oAttribute)
Next
oRoot.Elements.Add(oElement)
oRoot = oElement
Case XmlReaderNodeType.EndElement
If (enam = "if" Or enam = "while" Or enam = "else") And iab > 4 Then
cp = tvcode.Item.ParentKey
sv = CInteger(cp)
sv = sv - 1
cp = CString(sv)
Endif
oRoot = oRoot.Parent
Case XmlReaderNodeType.Text
oElement.Value &= Trim(oXml.Node.Value)
'Message.Info(oXml.Node.Value)
If enam <> "slyproj" And enam <> "prognam" Then
tvcode.Add(CString(iab), enam & " " & oXml.Node.Value, cond, cp).EnsureVisible
tvcode.Item.EnsureVisible
ablocks[iab] = New Block
ablocks[iab].tp = enam
ablocks[iab].father = False
iab = iab + 1
Else If enam = "prognam" Then
progname = oXml.Node.Value
Endif
End Select
oXml.Read()
Loop
oXml.Close()
si il problema era che la treeview era vuota (null object) ora và (sembra di si testato)