Autor Beitrag
SnuSnu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 17



BeitragVerfasst: Fr 20.03.09 12:40 
Hallo,

ich habe ein kleines Problem mit dem CDATA Tag in meiner xml. Mit den IXMLDocument und IDOMDocument Units erstelle ich wie folgt ein XML Dokument:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
var
   lXMLDocument: IXMLDocument;
  iXMLDom : IDOMDocument;
   lNode: IXMLNode;
   lNode2: IXMLNode;
   lNode3: IXMLNode;
   lNode4: IXMLNode;
   streamValidate : TStringStream;
begin
  // Pflichtfelder prüfen
   if not (edtRole.Text <> ''then begin
    MessageDlg('Bitte geben Sie eine Benutzergruppe an.', mtInformation, [mbOK], 0);
      edtRole.SetFocus;
      exit;
   end;
   if not (edtKurs.Text <> ''then begin
    MessageDlg('Bitte geben Sie eine Kurs ID an.', mtInformation, [mbOK], 0);
      edtKurs.SetFocus;
      exit;
   end;

  // XML Dokument
  lXMLDocument := newXMLDocument;
  lXMLDocument.Options := [doNodeAutoCreate, doAutoSave];
  lXMLDocument.ParseOptions := [];
  lXMLDocument.Encoding := 'ISO-8859-1';
  lXMLDocument.Active := True;

   // Rootnode schreiben
   lNode := lXMLDocument.AddChild('Users');

   // Erstellen und füllen der Nodes
   cdsPersonal.First;
   try
     while not cdsPersonal.Eof do begin

         //Sollte das übernehmen nicht markiert sein, dann wird die nächste Reihe aufgerufen
         if cdsPersonal.FieldByName('Checked').AsInteger = cnsCdsCheckedFalse then begin
            cdsPersonal.Next;
            continue;
         end;

         // User
         lNode2 := lNode.AddChild('User');
         lNode2.Attributes['Id'] := cdsPersonal.FieldByName('PersonalI3D').AsString;
         lNode2.Attributes['Language'] := 'de';
         lNode2.Attributes['Action'] := 'Insert';

            // Active
            lNode3 := lnode2.AddChild('Active');
            lNode3.NodeValue := '@@cdatastart true @@cdataende';

            // Role_1
            lNode3 := lnode2.AddChild('Role');
            lNode3.Attributes['Id'] := '_1';
            lNode3.Attributes['Type'] := 'Global';
            lNode3.Attributes['Action'] := 'Assign';
            lNode3.NodeValue := edtRole.Text;

            // Role_2
            lNode3 := lnode2.AddChild('Role');
            lNode3.Attributes['Id'] := '_2';
            lNode3.Attributes['Type'] := 'Global';
            lNode3.Attributes['Action'] := 'Assign';
            lNode3.NodeValue := 'il_crs_member_' + edtKurs.Text;

            // Login
            lNode3 := lnode2.AddChild('Login');
            lNode3.NodeValue := cdsPersonal.FieldByName('Name').AsString;

            // Password
            lNode3 := lnode2.AddChild('Password');
            lNode3.Attributes['Type'] := 'ILIAS3';
            lNode3.NodeValue := cdsPersonal.FieldByName('Vorname').AsString;

            // Gender
            lNode3 := lnode2.AddChild('Gender');
            lNode3.NodeValue := '';

            // Firstname
            lNode3 := lnode2.AddChild('Firstname');
            lNode3.NodeValue := cdsPersonal.FieldByName('Vorname').AsString;

            // Lastname
            lNode3 := lnode2.AddChild('Lastname');
            lNode3.NodeValue := cdsPersonal.FieldByName('Name').AsString;

            // Email
            lNode3 := lnode2.AddChild('Email');
            lNode3.NodeValue := cdsPersonal.FieldByName('Email').AsString;

      cdsPersonal.Next;
      end;
   finally
      cdsPersonal.First;
   end;

   // XML auf Sonderzeichen und Textmarken validieren
   streamValidate := TStringStream.Create(EmptyStr);
   lXMLDocument.SaveToStream(streamValidate);
   lXMLDocument.LoadFromStream(ValidateXML(streamValidate));

   // XML Schreiben
  fXMLDocument := lXMLDocument;

   // Speicherpfad
    if SelectDirectory('Verzeichnis auswählen:''', strPath ) then begin
    strPath := IncludeTrailingBackslash(strPath);
  end;

   // Speichern
   SaveFile(StrPath);

   // Schliessen
   actSchliessen.Execute;


Da diese keine CDATA Tags unterstützen, dachte ich mir ich speichere die XML in einen Stream und lese diesen Stream in einen String. Dort werden dann Textmarken ersetzt um dieses CDATA reinubekommen :

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
function TdlgPersonalInsIlias.ValidateXML(var Stream: TStringStream): TStringStream;
var
   strStream : String;
   StreamResult : TStringStream;
begin
  try
      // Stream in String laden
      strStream := Stream.DataString;

      // Zeilenumbrüche ersetzen
      strStream := StringReplace(strStream, '''''', [rfReplaceAll]);
      strStream := StringReplace(strStream, '#$D#$A''', [rfReplaceAll]);

      // Textmarken ersetzen
      strStream := StringReplace(strStream, '@@cdatastart''<![CDATA[', [rfReplaceAll]);
      strStream := StringReplace(strStream, '@@cdataende'']]>', [rfReplaceAll]);

      // String wieder in Stream laden
      StreamResult := TStringStream.Create(strStream);
      StreamResult.Position := 0;
      // Stream als Result zurück geben
      Result := StreamResult;
   finally
      if assigned(StreamResult) then
        FreeAndNil(StreamResult);
   end;
end;


Komischerweise wird mir in den String ein ' Zeichen eingefügt, das ich so auch nicht herausbekommen. Genauso wenig das '#$D#$A'.
Dies ist auch der Grund für den Error beim erstellen der XML.

Meine Frage hierzu:

Wie bekomme ich diese Zeichen heraus oder wie kann ich ohne größeren Aufwand und ohne abändern/ersetzen der Units einen CDATA Tag reinbekommen ?

Bedanke mich schonmal im Vorraus für jeglichen Mühen eurerseits =)
gruß Snu
ffgorcky
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 573

WIN XP/2000 & 7Prof (Familie:Win95,Win98)

BeitragVerfasst: Sa 23.05.09 16:35 
Also ich denke, dass man die Zeilenumbrüche so ersetzen kann:
ausblenden Delphi-Quelltext
1:
strStream := StringReplace(strStream, #13#10'', [rfReplaceAll]);					

Damit würde dann
so ein Text so aussehen:
ausblenden Delphi-Quelltext
1:
strStream='Damit würde dannso ein Text so aussehen:'					

Also wäre es besser, wenn man denn dort auch als Ersatz nicht einfach einen Leerstring setzt, sondern wieder ein Leerzeichen.
...Wobei auch ab und an nur die #10 genutzt werden muss, da dann kein Ende der Zeile (also #13) vermerkt ist, sondern nur der Zeilenumbruch (also #10) - warum auch immer.

Das müsste dann ja auch mit Deinem #$D#$A genauso gehen, denn ich meine, dass das das gleiche ist, nur eben anders bezeichnet. (Da steht wahrscheinlich das Zeichen $ für die zehner-1, das D für 3 und das $A für 0[=Null].)
SvenAbeln
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 334
Erhaltene Danke: 3



BeitragVerfasst: Sa 23.05.09 18:48 
user profile iconffgorcky hat folgendes geschrieben Zum zitierten Posting springen:

Das müsste dann ja auch mit Deinem #$D#$A genauso gehen, denn ich meine, dass das das gleiche ist, nur eben anders bezeichnet. (Da steht wahrscheinlich das Zeichen $ für die zehner-1, das D für 3 und das $A für 0[=Null].)

Nein das $ steht für die Darstellung der Zahl als Hexadezimal und damit A = 10 und D = 13.


user profile iconSnuSnu hat folgendes geschrieben Zum zitierten Posting springen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
 [...]
      // String wieder in Stream laden
      StreamResult := TStringStream.Create(strStream);
      StreamResult.Position := 0;
      // Stream als Result zurück geben
      Result := StreamResult;
   finally
      if assigned(StreamResult) then  
        FreeAndNil(StreamResult);  <----  Hier wird das Objekt zerstört und Result ist nun ungültig
   end;
end;



Wenn du ein Objekt als Result zurückgeben willst, darfst du es nicht innerhalb der Funktion wieder zerstören.