Domino 9 und frühere Versionen > ND8: Entwicklung

Import XML mit NotesDOMParser class

<< < (2/3) > >>

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