Domino 9 und frühere Versionen > ND8: Entwicklung
Import XML mit NotesDOMParser class
Peter Klett:
Das ganze Teil läuft sicherlich in einer Schleife.
Beim ersten Durchlauf, bei dem nodename vermutlich "machineID" ist, wird doc dimensioniert, doc erstellt, die Felder belegt und schließlich gespeichert.
Beim zweiten Durchlauf, bei dem nodename "machineManufacturer" ist, wird doc wieder dimensioniert, nicht erstellt, Feldwerte hineingeschrieben und gespeichert.
Vermutlich hast Du oben in Deinem Script ein On Error Resume Next (-> zu deutsch, "auch wenns knallt, Augen zu und durch"), sonst müsste Dir das Script mit einem Object variable not set aussteigen.
Das Dim doc As NotesDocument darf auf keinem Fall in der Schleife stehen. Auch die anderen Dim's gehören da nicht hin, führen aber vermutlich nicht zu einem Fehler, sondern kosten nur Rechenzeit. Möglicherweise vernichtet das Dim db auch das doc, müsste man ausprobieren, bzw. besser, raus aus der Schleife damit.
Wenn doc korrekt definiert wäre, sehe ich noch folgende Probleme im Script
Wenn machineManufacturer vor machineID im XML steht, wird kein Dokument erstellt, denn das passiert nur bei machineID (möglich, dass die Datei das so hergibt, kann ich nicht beurteilen). Object variable not set wäre der logische Folgefehler.
Bei jeder Veränderung des Dokuments (neues Feld) wird das Dokument gespeichert, auch das kostet Rechenzeit. Dass jedesmal die Form mit dem gleichen Wert überschrieben wird, ist eigentlich nicht kritisch, zeugt aber von einem suboptimalen Script.
Richtig kann es also nur so sein:
Dokument erstellen
Standardfelder füllen (z.B. Form)
Alle Felder (Items) zum Dokument füllen
Nächstes Dokument? -> Dokument speichern, neues Dokument erstellen
Standardfelder füllen (z.B. Form)
Alle Felder (Items) zum neuen Dokument füllen
usw.
manderson:
Guten Morgen!
Habe die DIMs aus der Schleife entfernt, aber das bringt es auch noch nicht, wäre ja auch zu schön gewesen :) Kurz noch: machineID steht in der xml vor machineManufacturer. ;)
Wenn ich mit den debugger Schritt für Schritt durch gehe, sehe ich auch das ein Wert für machineManufacturer bei node -> firstchild vorhanden ist. Lasse ich bei machineManufacturer, ähnlich wie für machineID ein neues Dokument erstellen, dann trägt er den Wert für machineManufacturer im neuen Dokument auch ein. Also irgendwo verlieren ich also den Zugriff auf das frisch erstellte Dokument oder liegt ich da falsch? Ist der call save befehl daran schuld? habe es auch schon nur bei machineManufacturer, sowie auserhalb der Schleife mal rein gepackt aber kein Erfolg.
Hier mal meine Daten:
Decleration
--- Code: ---Dim domParser As NotesDOMParser
Dim LF As String
Public doc As NotesDocument
--- Ende Code ---
--- Zitat ---Sub Initialize
Dim session As NotesSession
Dim db As NotesDatabase
Dim inputStream As NotesStream, outputStream As NotesStream
Dim docNode As NotesDOMDocumentNode
Dim origXML As String, outputFile As String
origXML = "c:\dxl\xmldom.xml"
outputFile = "c:\dxl\DOMtree.txt"
Dim header As String
header = "Walk Tree agent"
LF = Chr(13)+Chr(10)
On Error Goto errh
Set session = New NotesSession
Set db = session.CurrentDatabase
'create the output file
Set outputStream =session.CreateStream
outputStream.Open (outputFile)
outputStream.Truncate
'write report title
outputStream.WriteText ("DOM Parser Report - " )
outputStream.WriteText (header+LF)
'open the XML file
Set inputStream = session.CreateStream
inputStream.Open (origXML)
If inputStream.Bytes = 0 Then
outputStream.WriteText (origXML+" is empty"+LF)
Goto results
End If
'create DOM parser and process
Set domParser=session.CreateDOMParser(inputStream, outputStream)
domParser.Process
'get the document node
Set docNode = domParser.Document
Call walkTree(docNode)
results:
Call outputStream.Close
Exit Sub
errh:
outputStream.WriteText ("errh: "+Cstr(Err)+": "+Error+LF)
Resume results
End Sub
--- Ende Zitat ---
Un der Walktree + meine kaputter Block
--- Code: ---Sub walkTree ( node As NotesDOMNode)
Dim child As NotesDOMNode
Dim elt As NotesDOMNode
Dim attrs As NotesDOMNamedNodeMap
Dim a As NotesDOMAttributeNode
Dim piNode As NotesDOMProcessingInstructionNode
Dim doc As NotesDocument
Dim session As NotesSession
Dim db As NotesDatabase
Set session = New NotesSession
Set db = session.CurrentDatabase
LF = Chr(13)+Chr(10)
If Not node.IsNull Then
Select Case node.NodeType
Case DOMNODETYPE_DOCUMENT_NODE: ' If it is a Document node
domParser.Output( "Document node: "+node.Nodename )
Set child = node.FirstChild ' Get the first node
Dim numChildNodes As Integer
numChildNodes = node.NumberOfChildNodes
domParser.Output(" has "+Cstr(numChildNodes)+" Child Nodes"+LF)
While numChildNodes > 0
Set child = child.NextSibling ' Get next node
numChildNodes = numChildNodes - 1
Call walkTree(child)
Wend
Case DOMNODETYPE_DOCUMENTTYPE_NODE: ' It is a <!DOCTYPE> tag
domParser.Output("Document Type node: "+ node.NodeName+LF)
Case DOMNODETYPE_TEXT_NODE: ' Plain text node
domParser.Output("Text node: "+node.NodeValue+LF)
Case DOMNODETYPE_ELEMENT_NODE: ' Most nodes are Elements
domParser.Output("Element node: "+node.NodeName )
Set elt = node
'XMl Daten in die db schreiben
If node.nodename = "machineID" Then
Set doc = db.CreateDocument
doc.form = "form_machine"
'doc.machineId = Node.Firstchild.Nodevalue
Call doc.ReplaceItemValue("machineID", Node.Firstchild.Nodevalue)
Call doc.Save(true, true)
End If
If node.nodename = "machineManufacturer" Then
doc.form = "form_machine"
Call doc.ReplaceItemValue("machineManufacturer", Node.Firstchild.Nodevalue)
Call doc.Save(True, true)
End If
Dim numAttributes As Integer, numChildren As Integer
numAttributes = elt.attributes.numberofentries
domParser.Output(" has "+Cstr(numAttributes)+" Attributes"+LF)
Set attrs = elt.Attributes ' Get attributes
Dim i As Integer
For i = 1 To numAttributes ' Loop through them
Set a = attrs.GetItem(i)
' Print attr. name & value
domParser.Output("Attribute "+a.NodeName+": "+a.NodeValue+LF)
Next
numChildren = elt.NumberOfChildNodes
Set child = elt.FirstChild ' Get child
While numChildren > 0
Call walkTree(child)
Set child = child.NextSibling ' Get next child
numChildren = numChildren - 1
Wend
domParser.Output( elt.nodeName+LF)
Case DOMNODETYPE_COMMENT_NODE: ' Comments
domParser.Output("Comment node: "+node.NodeValue+LF)
Case DOMNODETYPE_PROCESSINGINSTRUCTION_NODE: ' Handle PI nodes
Set piNode = node
domParser.Output("Processing Instruction node: " )
domParser.Output(" with Target "+piNode.Target+_
" and Data "+piNode.Data+LF)
Case DOMNODETYPE_CDATASECTION_NODE: ' CDATA sections
domParser.Output("CDATA Section node: "+node.NodeName)
domParser.Output(" has value of "+node.NodeValue+LF)
Case DOMNODETYPE_ENTITYREFERENCE_NODE: ' Handle entities
domParser.Output("Entity Reference node: "+node.NodeName+LF)
Case Else:
domParser.Output("Ignoring node: "+Cstr(node.NodeType)+LF)
End Select 'node.NodeType
End If 'Not node.IsNull
End Sub
--- Ende Code ---
manderson:
hmm DOMtree.txt spuckt nun folgendes aus:
--- Zitat ---DOM Parser Report - Walk Tree agent
Document node: #document has 2 Child Nodes
Element node: machineList has 0 Attributes
Text node:
Element node: machine has 0 Attributes
Text node:
Element node: machineID has 0 Attributes
Text node: 123456Machine
machineID
Text node:
Element node: machineManufacturererrh: 91: Object variable not set
--- Ende Zitat ---
manderson:
Ohne Dim doc As NotesDocument geht es... ich könnte schrein.... ;D
Naja so lernt man halt
Peter Klett:
Völlig logisch. Du hast doc global declariert und in Deiner WalkTree-Funktion rufst Du die Funktion selbst wieder auf: Call walkTree(child)
Der rekursive Aufruf soll das gleiche Dokument bearbeiten, und mit dem zusätzlichen und unnötigen Dim doc As NotesDocument in der Funktion hast Du das alte doc im Speicher vernichtet, daran hat das doc.Save keine Schuld.
Das ist also Deine Schleife, innerhalb der Du doc nicht neu dimensionieren darfst. Im ersten Versuch hattest Du es nur aus der Case-Bedingung herausgenommen, aber nicht aus der Schleife. Beim rekursiven Aufruf einer Funktion, die mit dem gleichen Dokument arbeiten soll, musst Du es entweder global deklarieren (wie Du es getan hast) oder es der Funktion als Parameter mitgeben, was ich persönlich eleganter finde (nur "Bauchgefühl").
Navigation
[0] Themen-Index
[#] Nächste Seite
[*] Vorherige Sete
Zur normalen Ansicht wechseln