XML, sehr lange Texte exportieren

8. Oktober 2012 13:48

Hallo Zusammen,

mein Problem bezieht sich auf den CC.

Ich möchte gerne Zeilen in Nav auslesen und zu einer sehr langen Zeile zusammenknüpfen (zB 10.000). Leider macht irgendwas "dicht", so das ich einen Stackspeicher-Fehler bekomme. Rekursion ist ausgeschlossen.

Das hier funktioniert (immerhin ca 2048 Zeichen):
NewChildNode = 'Microsoft XML, v3.0'.IXMLDOMNode

Code:
lText1024 := '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' +
             '012345678901234567890123';

NewChildNode.text := lText1024 + lText1024;


Wenn ich noch ein lText1024 anhänge "knallt" es. Genauer gesagt würde schon 1 Zeichen mehr reichen.

Hat einer von Euch eine Idee, wie ich sehr lange Texte exportiert bekomme.
Könnte sowas gehen, wenn ich mit einem Stream arbeite? -->Allerdings habe ich da nicht ganz so viel Ahnung, wäre daher ggf um ein Beispiel dankbar.

Re: XML, sehr lange Texte exportieren

8. Oktober 2012 14:00

An welcher Stelle ist Rekursion ausgeschlossen?

Woher kommen die Daten für den langen String?

Re: XML, sehr lange Texte exportieren

8. Oktober 2012 14:02

Derzeit Teste ich so wie oben beschrieben.
Also ich fülle einfach einen String und hänge die mit '+' (plus) aneinander.

Das geht zB ja auch sehr gut beim schreiben von Textdateien mit dem Datentyp "File".

Also Rekursion deswegen ausgeschlossen, weil ich hier keine Schleife verwende. Normalerweise kommen "Stack" Fehler ja bei rekursiven Aufrufen.

Re: XML, sehr lange Texte exportieren

8. Oktober 2012 14:06

Geh mal in die C/AL Hilfe und suche nach BLOB. Und vom BLOB Data Type in die createin/outstream Funktionen. Das sollte die Lösung sein.

Re: XML, sehr lange Texte exportieren

8. Oktober 2012 14:34

habs gerade gelesen.

Nur wie bekomme ich die XML Struktur und den Langtext in eine XML Datei geschrieben?

bzw (so denke ich zumindest), ich müsste also erst die gesammte XML Datei in ein BLOB schreiben, Ok.
Nur wie, ich arbeite ja nicht mit einem XMLPort, sondern mit den "ms xml IXMLDOMNode" Objekten?!

Re: XML, sehr lange Texte exportieren

8. Oktober 2012 14:37

Hier bzw. hier sind ähnliche Probleme, nutzen die Streams via der TempBlob-Tabelle.

Re: XML, sehr lange Texte exportieren

10. Oktober 2012 09:15

Danke für die Links,

alles was mit einem XML-Port zu tun hat, kann ich meinem ermessen nach nicht verwenden, da ich ja mit MSXML Objekten arbeite (Automation).

Im zweiten Link wird das hier geschrieben:
Code:
CLEAR(TempBlob.Blob);
TempBlob.Blob.CREATEOUTSTREAM(Outstr);
XmlDoc.save(Outstr);


Nur komme ich nicht soweit, dass ich ein "xmlDoc.save" ausführen könnte.
Es gibt bereits vorher ein Problem, wenn ich diese Methode aus der MSXML DOMDocument automation Variable anspreche.

Aber eigentlich kann ich mir nicht so recht vorstellen, dass es nicht möglich sein soll, beliebig viele Zeichen zu schreiben.

Re: XML, sehr lange Texte exportieren

10. Oktober 2012 10:43

mikka hat geschrieben:Aber eigentlich kann ich mir nicht so recht vorstellen, dass es nicht möglich sein soll, beliebig viele Zeichen zu schreiben.

Die Links waren als Hinweis zum Nutzen der Exportfunktion der TempBlobtabelle gedacht. Man kann alles nacheinander mit WRITETEXT in die TempBlob einstreamen und als ein große Datei ausstreamen. Damit geht es auf jeden Fall. Ich bin selber momentan damit beschäftigt, überlange Mailtexte als Anhang an MAPI-Mails (Microsoft MAPI Messages Control, version 6.0) anzuhängen, und habe so Anhänge mit über 4000 Zeichen erzeugt. Mehr würden sicher auch noch gehen (ein BLOB hat eine max. Größe von 2GB), brauche ich aber derzeit nicht :-).

Das BLOB manuell auszulesen geht auch (Link), das komplette Auslesen erledigt die EXPORT-Funktion aber direkt.

Re: XML, sehr lange Texte exportieren

10. Oktober 2012 14:35

Hallo,

@Kowa:
Mikka möchte den langen Text als Knoten im XML ausgeben, nicht den Blob als XML-Datei. Mit Bigtext.GETSUBTEXT() und/bzw. XMLNode.insertdata sollte man das bewerkstelligen können, was Mikka vor hat.

Zu deinem Mail- Problem:

die CU 397 hat die schöne Funktion AddBodyLine, die ist in der aktuellen Version nicht mehr zeilenweise, d.h. wenn man kein CRLF in den TExt einfügt, dann macht die auch keine Vorschub im MailBody.

Gruß, Fiddi

Re: XML, sehr lange Texte exportieren

10. Oktober 2012 15:35

fiddi hat geschrieben:Zu deinem Mail- Problem:
die CU 397 hat die schöne Funktion AddBodyLine, die ist in der aktuellen Version nicht mehr zeilenweise, d.h. wenn man kein CRLF in den TExt einfügt, dann macht die auch keine Vorschub im MailBody.

Das würde ich gerne nutzen, aber die aktuellen (auf Outlook abgestimmten) Mailautomations funktionieren leider nicht mit zusammen mit Lotus Notes, deshalb kann ich leider nur das einfache MAPI nutzen. Mehr als 1024 Zeichen kann ich nicht in den MsgNoteText zuweisen, sonst bekomme ich auch einen Stackspeicherfehler wie Mikka oben.

Re: XML, sehr lange Texte exportieren

10. Oktober 2012 15:43

Das würde ich gerne nutzen, aber die aktuellen (auf Outlook abgestimmten) Mailautomations funktionieren leider nicht mit zusammen mit Lotus Notes, deshalb kann ich leider nur das einfache MAPI nutzen. Mehr als 1024 Zeichen kann ich nicht in den MsgNoteText zuweisen, sonst bekomme ich auch einen Stackspeicherfehler wie Mikka oben.


Rein theoretisch sollte das egal sein. Ich würde aber zwei Dinge tun:
1. Die Variablen würde ich als VAR- Parameter an Funktionen übergeben, bzw. große Variablen als globale Variablen anlegen, dann landen Sie nicht auf dem Stack
2. Die Funktion AddBoddyline enthält Funktionsaufrufe aus "BSTRConverterBody", die haben nichts mit MAPI zu tun.

Gruß, Fiddi

Re: XML, sehr lange Texte exportieren

10. Oktober 2012 17:42

fiddi hat geschrieben:2. Die Funktion AddBoddyline enthält Funktionsaufrufe aus "BSTRConverterBody", die haben nichts mit MAPI zu tun.

Dem Body können diese in der aktuellen Version aber direkt zugewiesen werden, das geht mit den einfachen MAPI Messages nicht. Da wird Text erwartet.
MailBody.jpg

aber Dank diesem Tipp
fiddi hat geschrieben:bzw. große Variablen als globale Variablen anlegen, dann landen Sie nicht auf dem Stack

ist das auch gar nicht mehr notwendig :!: Ich kann die mit GETSUBTEXT erstellten 1024er Textblöcke wie geplant einmal verketten und direkt in den Mail-Body schreiben ohne Anhänge erzeugen zu müssen. Genau da kommt sonst der Stacküberlauf. So reicht es zumindest für 2048 Zeichen im Body, bevor auf die Anhänge ausgewichen werden muss.
So klappt es bei mir, vielleicht kommt Mikka damit ja auch weiter :-) .
Code:
TempBlob.DELETEALL;
TempBlob."Primay Key" := 1;
TempBlob.INSERT;
TempBlob.Blob.CREATEOUTSTREAM(MailOutStream);
MailOutStream.WRITETEXT(GanzLangerText);
MailOutStream.WRITETEXT();
... // hier folgen etliche weitere WRITETEXT-Zeilen
TempBlob.MODIFY;
// nur zur Kontrolle auch als Datei exportieren
TempBlob.Blob.EXPORT('C:\KontrolldateiMailInhalt.txt',FALSE);
TempBlob.Blob.CREATEINSTREAM(MailInStream);
TempBlob.CALCFIELDS(Blob);
TestBigText.READ(MailInStream);
TestBigText.GETSUBTEXT(MailBodyText,1);
MessageLength := MailBodyText.LENGTH;
IF MessageLength IN  [1..1024] THEN BEGIN
  MailBodyText.GETSUBTEXT(FirstSegment,1,1024);
  MAPIMessages.MsgNoteText := FirstSegment;
END ELSE IF MessageLength IN [1025..2048] THEN BEGIN // das geht noch durch
  MailBodyText.GETSUBTEXT(FirstSegment,1,1024);
  MailBodyText.GETSUBTEXT(SecondSegment,1025,1024);
  MAPIMessages.MsgNoteText := FirstSegment + SecondSegment;
END ELSE IF MessageLength IN [2049..3072] THEN BEGIN // das nicht mehr, Abbruch wegen Stacküberlauf
  MailBodyText.GETSUBTEXT(FirstSegment,1,1024);
  MailBodyText.GETSUBTEXT(SecondSegment,1025,1024);
  MailBodyText.GETSUBTEXT(ThirdSegment,2049,1024);
  MAPIMessages.MsgNoteText := FirstSegment + SecondSegment + ThirdSegment;
END

Hinweis zum Code: MailBodyText und TestBigText sind BigText-Variablen, die Segmente dann normale Textvariablen.
Danke :!:
Edit : Die Abfage, ob das BLOB einen Inhalt ist , erledigt das System beim READ selber, sonst kommt:
Stream.png
die Error Message habe ich deshalb im Beispielcode entfernt.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Re: XML, sehr lange Texte exportieren

10. Oktober 2012 21:39

Code:
i:=1;
SegLen := 1024;
while (i < Mailbodytext.length) do begin
   if (MailBodyText.length -i) < SegLen then
     SegLen := MailBodyText.length -i;
   MailBodyText.getsubtext(Segment,i,Seglen);
   APIMessages.MsgNoteText += Segment;
end;


funktioniert nicht? (Code nicht getest)

Gruß, Fiddi

Re: XML, sehr lange Texte exportieren

11. Oktober 2012 12:15

fiddi hat geschrieben:
Code:
i:=1;
SegLen := 1024;
while (i < Mailbodytext.length) do begin
   if (MailBodyText.length -i) < SegLen then
     SegLen := MailBodyText.length -i;
   MailBodyText.getsubtext(Segment,i,Seglen);
   APIMessages.MsgNoteText += Segment;
end;


funktioniert nicht? (Code nicht getest)

Gruß, Fiddi

Sieht elegant aus, klappt aber auch nicht :wink:.
Das Compound Assignment += in der letzten Zeile geht mit dem Automationproperty nicht, nur als normale Zuweisung
Code:
  MAPIMessages.MsgNoteText := MAPIMessages.MsgNoteText + Segment;

Ein Stacküberlauf kommt so zwar nicht, leider kommt selbst unter 1024 Zeichen dann in dieser Zeile ein Abbruch mit
"Die Länge des Textstrings überschreitet die Größe des Zeichenpuffers".

Re: XML, sehr lange Texte exportieren

11. Oktober 2012 13:07

Warum benutzt du nicht MAPIMessages.Body anstatt MAPIMessages.MsgNoteText?

Gruß, Fiddi

Re: XML, sehr lange Texte exportieren

11. Oktober 2012 13:22

fiddi hat geschrieben:Warum benutzt du nicht MAPIMessages.Body anstatt MAPIMessages.MsgNoteText?

Weil das einfache MAPI kein Body-Property hat. Das hier sind die Möglichkeiten:
http://msdn.microsoft.com/en-us/library ... 60%29.aspx

Re: XML, sehr lange Texte exportieren

11. Oktober 2012 14:24

Probier doch mal folgendes:
Code:
    i:=1;
    SegLen := 1024;
    while (i < Mailbodytext.length) do begin
       if (MailBodyText.length -i) < SegLen then
         SegLen := MailBodyText.length -i;
       MailBodyText.getsubtext(Segment,i,Seglen);
       APIMessages.MsgNoteText .= Segment;
    end;


Der einzige Unterschied ist das fehlende '+'. D.h. die simple Zuweisung fügt das neue Segment an.

Gruß, Fiddi

Re: XML, sehr lange Texte exportieren

11. Oktober 2012 15:47

fiddi hat geschrieben:Probier doch mal folgendes:
Code:
    i:=1;
    SegLen := 1024;
    while (i < Mailbodytext.length) do begin
       if (MailBodyText.length -i) < SegLen then
         SegLen := MailBodyText.length -i;
       MailBodyText.getsubtext(Segment,i,Seglen);
       APIMessages.MsgNoteText .= Segment;
    end;

Der einzige Unterschied ist das fehlende '+'. D.h. die simple Zuweisung fügt das neue Segment an.

".=" gibt es nicht, falls du ":=" meintest, damit kommt nur das letzte Segment an.
Hatte ich oben vorhin vergessen: Hochzählen muss man i unten natürlich auch, sonst wird es eine Endlosschleife.
Code:
i += STRLEN(Segment);

Re: XML, sehr lange Texte exportieren

11. Oktober 2012 16:03

Wenn ich das eben richtig im OCX gesehen habe, dann erwartet MsgNoteText Als Zuweisung einen BSTR und das ist genau das Ergebnis von BSTRConverterBody.BSTR, womit wir wieder am Anfang meiner Ausführungen wären :wink:

Gruß,Fiddi

Re: XML, sehr lange Texte exportieren

11. Oktober 2012 16:41

fiddi hat geschrieben:Wenn ich das eben richtig im OCX gesehen habe, dann erwartet MsgNoteText Als Zuweisung einen BSTR und das ist genau das Ergebnis von BSTRConverterBody.BSTR, womit wir wieder am Anfang meiner Ausführungen wären :wink:
Prinzipiell schon, aber wenn man mit AddBodyLine den BSTRConverterBody füllt und dann in den MsgNoteText zuweist, dann ist beim Zeichenpuffer wieder Endstation, wenn 1024 Zeichen überschritten werden. Die einzelnen Komponenten können jede für sich sicher mehr.
Zeichenpuffer.jpg
Mach' dir nicht so viel Gedanken, In meinem Fall reichen die 2048 Zeichen vermutlich für 99% aller Fälle, wenn es doch mal mehr werden, kann man die Textdatei als Anhang an die Mail hängen. Da das nur für interne Mails verwendet wird, müssen wir nicht in Schönheit sterben :wink: . Auf die Streams hatte ich hier nur umstellen müssen, weil die 1024er Grenze sonst regelmäßig gesprengt werden würde.

Wenn Mikka sich wieder meldet, können wir ja weiterbohren :-) .
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Re: XML, sehr lange Texte exportieren

11. Oktober 2012 17:05

Ruf das mal als Funktion auf MsgNoteText(BSTR);

Gruß, Fiddi

Re: XML, sehr lange Texte exportieren

12. Oktober 2012 09:29

fiddi hat geschrieben:Ruf das mal als Funktion auf MsgNoteText(BSTR);

Verhält sich genauso wie die Zuweisung. Jenseits der 1024 Zeichen wieder "Endstation Zeichenpuffer".

Re: XML, sehr lange Texte exportieren

15. Oktober 2012 14:16

Kowa hat geschrieben:Das BLOB manuell auszulesen geht auch (Link), das komplette Auslesen erledigt die EXPORT-Funktion aber direkt.

…solange man keine ASCII-ANSI Konvertierung benötigt :wink:.Statt der einen EXPORT-Zeile muss man dann im Code zeilenweise auslesen, um z.B. die Funktionen in CU 11501 nutzen zu können.
Code:
TempBlob.Blob.CREATEINSTREAM(MailInStream); 
AttachmentFile.CREATE(AttachmentPathAndName);
AttachmentFile.WRITEMODE(TRUE);
AttachmentFile.TEXTMODE(TRUE);
WHILE NOT MailInStream.EOS DO BEGIN
  MailInStream.READTEXT(ExportLine);
    ExportLine := DELCHR(GeneralMgt.Ascii2Ansi(ExportLine),'<',' ');
    AttachmentFile.WRITE(ExportLine);
  END;
AttachmentFile.CLOSE;