[Gelöst]Problem mit DOM - getElementsByTagName

Programmierung unter AOO/LO (StarBasic, Python, Java, ...)

Moderator: Moderatoren

preklov
***
Beiträge: 76
Registriert: Mo, 29.06.2009 09:04
Wohnort: Ruhrgebiet

[Gelöst]Problem mit DOM - getElementsByTagName

Beitrag von preklov »

Hallo, ich bin neu hier.

Ich habe festgestellt, dass die Methode getElementsByTagName eines dom-Document-Trees zum Absturz von OpenOffice führt, wenn die gesuchten Felder aus nur 1 Tagfeld bestehen (z.B. <document ID="123" title="Ipp Zipp Zapp" />). Bei Feldern mit Anfangs- und Endetag klappt alles problemlos.

Kann jemand das Verhalten bestätigen? Ich habe kein Issue dazu gefunden.

Getestet mit StarBasic in OOO3.1 unter openSUSE 11.1 und Windows XT.

Gruß
Volker
Zuletzt geändert von preklov am Fr, 14.08.2009 09:32, insgesamt 1-mal geändert.
preklov
***
Beiträge: 76
Registriert: Mo, 29.06.2009 09:04
Wohnort: Ruhrgebiet

Re: Problem mit DOM - getElementsByTagName

Beitrag von preklov »

Ich habe nach weiteren Tests den Eindruck, dass mein Problem von der Größe der xml-Datei abhängt.

Die xml-Struktur sieht so aus:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<slots>
  <slot status="active" type="internal" ID="10001">
    <beta userID="X000001" systemID="Y000001" />
    <document ID="1234" title="Ipp Zipp Zapp" />
    <validTo>03.08.2009</validTo>
    <lecturer name="Becker, Bobbele" ID="1704" title="Dr." email="bobbeleb@dtb.de" />
    <orgUnit ID="01.01" label="Besenkammer" />
    <derivate ID="21905" modified="15.06.2009" />
  </slot>
</slots>
Das "slot"-Minimum ist das "beta"-Element. Alle anderen Elemente sind optional.

Mein StarBasic-Ansatz:

Code: Alles auswählen

Sub GetXMLData()
  dim oSimpleFileAccess as object
  dim oInputStream as object
  dim oDocBuilder as object
  dim oDocTree as object
  dim sUrl as string
  
  sUrl = "Z:\Eigene Dateien\testxml.xml"
  oSimpleFileAccess = createUnoService("com.sun.star.ucb.SimpleFileAccess")
  oInputStream = oSimpleFileAccess.openFileRead(ConvertToURL(sUrl))
  oDocBuilder = createUnoService("com.sun.star.xml.dom.DocumentBuilder")
  
  oDocTree = oDocBuilder.parse(oInputStream)
  
  oInputStream.closeInput()
  ParseXMLData(oDocTree)
End Sub

Sub ParseXMLData(oTree)
  dim oSlotList, oVtList, oDocList, oLectList as object

  oDocList = oTree.getElementsByTagName("document")
  print "Document-Nodes:", oDocList.getLength()
  oSlotList = oTree.getElementsByTagName("slot")
  print "Slot-Nodes:", oSlotList.getLength()
  oVtList = oTree.getElementsByTagName("validTo")
  print "ValidTo-Nodes:", oVtList.getLength()
  oLectList = oTree.getElementsByTagName("lecturer")
  print "Lecturer-Nodes:", oLectList.getLength()
End Sub
Ich habe die Listen in unterschiedlichen Kombinationen getestet. Wenn die xml-(Test-)Datei klein ist (4 slots, 2 kB), ist alles gut, bei einer großen echten aber (ca. 1300 slots, 476 kB) stürzt OpenOffice bei den "document"- und "lecturer"-Listen ab, obwohl sie etwas kleiner sind als die komplette "slot"-Liste.

An Strukturfehlern der xml-Datei kann es nicht liegen, denn der Zugriff über die Child-Nodes von slot funktioniert ohne jeglichen Fehler, ist aber relativ langsam.

Arbeitsspeicher 2 GB.

Hat jemand eine Idee?

Gruß
Volker
Schöne Grüße
Volker
preklov
***
Beiträge: 76
Registriert: Mo, 29.06.2009 09:04
Wohnort: Ruhrgebiet

Re: [Gelöst]Problem mit DOM - getElementsByTagName

Beitrag von preklov »

Mir scheint, ich habe den Fehler gefunden.

Der DOM-Parser erzeugt für jeden Zeilenumbruch mit/ohne folgende Einrückung einen Textnode. Wenn getElementsByTagName auf Elemente in Kurznotierung (<name att="val" />) angewendet wird, denen ein solcher Textnode folgt, stürzt OpenOffice (3.1) ab. Jedenfalls stellt es sich mir so dar.

Ich habe keine Methode gefunden, IgnorableWhitespace wie bei SAX beim Parsen zu eliminieren. Daher habe ich vor der Datenauswertung solche Nodes entfernt:

Code: Alles auswählen

Sub DeleteIgnorableWhitespace(oElement as object)

REM When importing xml files into a DOM tree line feeds and indentations
REM   are treated as text nodes.
REM I haven't found an import setting to care for ignorable white space.
REM Is this a bug?
REM
REM This procedure deletes all text nodes out of a DOM tree that consist
REM   of characters ascii 9 through 13 and 32.
REM It works recursively and needs a couple of seconds with big files.

  dim oChildren as object
  dim oChild as object
  dim i as integer
  dim r as integer
  
  if oElement.hasChildNodes() then
    oChildren = oElement.getChildNodes()
    for i = 0 to oChildren.getLength() - 1
      oChild = oChildren.item(i - r)
      if oChild.getNodeType() = com.sun.star.xml.dom.NodeType.TEXT_NODE then
        if IsWhite(oChild.getNodeValue()) then
          oElement.removeChild(oChild)
          r = r + 1
        end if
      else
        DeleteIgnorableWhitespace(oChild)
      end if
    next
  end if
End Sub

Function IsWhite(sString as string) as boolean
REM Tests if there are only whitespace characters in a string:
REM   ASCII 9 - 13, and 32.
  dim i as integer
  if sString <> "" then
    for i = 1 to len(sString)
      select case asc(mid(sString, i, 1))
      case 9 to 13, 32
      case else
        IsWhite = false
        exit function
      end select
    next
  end if
  IsWhite = true
End Function
Danach gab es keinen Absturz mehr. Allerdings dauert das etwas, bei etwa 1300 Datensätzen ca. 6 Sekunden. Workarounds mit enumerierten Nodelisten statt getElementsByTagName sind da wohl schneller.

Schöne Grüße
Volker
Schöne Grüße
Volker
Stephan
********
Beiträge: 12368
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: [Gelöst]Problem mit DOM - getElementsByTagName

Beitrag von Stephan »

Mir scheint, ich habe den Fehler gefunden.
Ich konnte Dir zwar nicht weiterhelfen, aber sage Dir ausdrücklich Danke dafür das Du hier die Allgemeinheit an DEiner selbstgefundenen Lösung, zu einer selbstaufgeworfenen Frage, teilhaben lässt.



Gruß
Stephan
Antworten