![]() |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
|
Re: Ideen für spezielle Stringbearbeitung
|
Re: Ideen für spezielle Stringbearbeitung
Zitat:
Wenn ich die MSXML2_TLB.pas in mein Projekt einfüge scheint das dennoch nicht zu klappen... |
Re: Ideen für spezielle Stringbearbeitung
Nein es gibt mehrere verschiedene XML-Parser von Microsoft. Diese Unit wrappt MSXML2
|
Re: Ideen für spezielle Stringbearbeitung
Delphi-Quellcode:
Datei MSXML2_TLB ist im Projektverzeichnis...
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, XMLFile, XMLDOM, XMLIntf, msxmldom, XMLDoc, MSXML2_TLB; kriege nun diesen Fehler: [DCC Fehler] dw_xml.pas(32): E2003 Undefinierter Bezeichner: 'CoDomDocument' |
Re: Ideen für spezielle Stringbearbeitung
Moin,
öffne mal ein Befehlseingabefenster und schau dir mit DIR %WINDIR%\system32\MSXML?.DLL an, was die höchste Version deines installierten MSXML-Parsers ist. Und dann besorge dir wahlweise den Wrapper für MSXML4 (mit XDR) oder MSXML6 (ohne XDR). Wahlweise kannst du dir den Wrapper selbst erstellen mit (D7): tlibimp -Fe- %windir%\system32\msxml4.dll Und beachte, dass im generierten Wrapper je nach Version von TLIBIMP bestimmte Bezeichner umbenannt werden. Freundliche Grüße |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
|
Re: Ideen für spezielle Stringbearbeitung
Hast du mal den Kommentar im Kopfteil von MSXML2_TLB.PAS durchgelesen?
Vielleicht wurde CoDomDocument umbenannt. |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
Delphi-Quellcode:
// Hinweis: Symbol 'DOMDocument' umbenannt zu 'msDOMDocument'
// Hinweis: Symbol 'DOMDocument26' umbenannt zu 'msDOMDocument26' // Hinweis: Symbol 'DOMDocument30' umbenannt zu 'msDOMDocument30' // Hinweis: Symbol 'FreeThreadedDOMDocument' umbenannt zu 'msFreeThreadedDOMDocument' // Hinweis: Symbol 'FreeThreadedDOMDocument26' umbenannt zu 'msFreeThreadedDOMDocument26' // Hinweis: Symbol 'FreeThreadedDOMDocument30' umbenannt zu 'msFreeThreadedDOMDocument30' // Hinweis: Symbol 'XMLSchemaCache' umbenannt zu 'msXMLSchemaCache' // Hinweis: Symbol 'XMLSchemaCache26' umbenannt zu 'msXMLSchemaCache26' // Hinweis: Symbol 'XMLSchemaCache30' umbenannt zu 'msXMLSchemaCache30' // Hinweis: Symbol 'XSLTemplate' umbenannt zu 'msXSLTemplate' // Hinweis: Symbol 'XSLTemplate26' umbenannt zu 'msXSLTemplate26' // Hinweis: Symbol 'XSLTemplate30' umbenannt zu 'msXSLTemplate30' // Hinweis: Symbol 'XMLHTTP' umbenannt zu 'msXMLHTTP' // Hinweis: Symbol 'XMLHTTP26' umbenannt zu 'msXMLHTTP26' // Hinweis: Symbol 'XMLHTTP30' umbenannt zu 'msXMLHTTP30' // Hinweis: Symbol 'ServerXMLHTTP' umbenannt zu 'msServerXMLHTTP' // Hinweis: Symbol 'ServerXMLHTTP30' umbenannt zu 'msServerXMLHTTP30' // Hinweis: Symbol 'SAXXMLReader' umbenannt zu 'msSAXXMLReader' // Hinweis: Symbol 'SAXXMLReader30' umbenannt zu 'msSAXXMLReader30' // Hinweis: Symbol 'MXXMLWriter' umbenannt zu 'msMXXMLWriter' // Hinweis: Symbol 'MXXMLWriter30' umbenannt zu 'msMXXMLWriter30' // Hinweis: Symbol 'SAXAttributes' umbenannt zu 'msSAXAttributes' // Hinweis: Symbol 'SAXAttributes30' umbenannt zu 'msSAXAttributes30' // Hinweis: Parameter 'type' im IXMLDOMNode.nodeType geändert zu 'type_' // Hinweis: Element 'implementation' von 'IXMLDOMDocument' geändert zu 'implementation_' // Hinweis: Parameter 'type' im IXMLDOMDocument.createNode geändert zu 'type_' // Hinweis: Parameter 'var' im IXMLDOMSchemaCollection.add geändert zu 'var_' // Hinweis: Symbol 'type' umbenannt zu 'type_' // Hinweis: Parameter 'type' im ISchemaElement.type geändert zu 'type_' // Hinweis: Symbol 'type' umbenannt zu 'type_' // Hinweis: Parameter 'type' im ISchemaAttribute.type geändert zu 'type_' |
Re: Ideen für spezielle Stringbearbeitung
Wenn du genau liest, dann findest du heraus, dass du ComsDOMDocument verwenden musst.
![]() |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
in Bezug auf deinen Beispielcode: kannst du mir noch erklären was das mit dem MARKUP und XPATH auf sich hat? ist das der Suchstring oder für was brauchts das? Wenn ich jetzt deinen Beispielcode ausführe erhalte ich nämlich nur die Meldung: Ein XML-Dokument muss ein Element der obersten Ebene enthalten. Ich blick immer noch nicht durch. |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
|
Re: Ideen für spezielle Stringbearbeitung
MARKUP ist bei mir einfach eine Konstante, bei dir der String mit dem DocuWare-XML, den du aus deiner Datenbank gelesen hast. Wenn mit dem XML-String irgendwas nicht stimmt, dann erhältst du eine Fehlermeldung, wie du ja gemerkt hast. Schau dir den XML-String mal genau an oder stelle den Text hier ein.
XPATH ist eine Spezifikation zur Addressierung einzelner DOM-Objekte. Der Zugriff über einen XPath-Ausdruck erspart dir umständliches Navigieren per Code. |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
hab jetzt den Markup zu einer Variable gemacht und meinen XML String zugewiesen. Dadurch erhalte ich nun die sehr aussagekräftige Meldung: "An dieser Stelle sind keine Leerzeichen zugelassen." Ich freue mich :) |
Re: Ideen für spezielle Stringbearbeitung
Dein XML-Dokument aus Beitrag #37 wird von meinem Beispiel-Code aus Beitrag #39 problemlos verarbeitet. Ich habe dein Dokument über die Zwischenablage in eine Datei kopiert und von dort zur Laufzeit in ein Memo geladen. Ich übergebe dann Memo.Text anstelle von MARKUP.
|
Re: Ideen für spezielle Stringbearbeitung
Zitat:
Delphi-Quellcode:
Und dabei krieg ich die erwähnte Meldung (im memo1.text ist genau der XML String drin welcher in Beitrag #37 drin steht... )
procedure Tfrmxml.Button1Click(Sender: TObject);
function CreateDocument(var doc: IXMLDOMDocument2; const markup: string): Boolean; begin doc := ComsDOMDocument.Create; doc.async := False; Result := doc.loadXML(markup); end; const { MARKUP = '' + '' + '' + '' + ' ' ;} XPATH = '//Basket[%d]/@path'; var anzahl: integer; i: integer; doc: IXMLDOMDocument2; n: IXMLDOMNode; MARKUP : string; begin MARKUP := memo1.text; if CreateDocument(doc, MARKUP) then begin n := doc.selectSingleNode(Format(XPATH, [1])); ShowMessage(VarToStr(n.nodeValue)); n.nodeValue := ExtractFilePath(ParamStr(0)); ShowMessage(doc.xml); end else ShowMessage(doc.parseError.reason); { XMLDocument1.LoadFromFile(getpath+'test.xml'); if xmldocument1.DocumentElement.NodeName='Baskets' then begin anzahl:=XMLDocument1.DocumentElement.Attributes['totalNumber']; for i := 0 to anzahl-1 do begin showmessage(XMLDocument1.DocumentElement.ChildNodes.Nodes[i].Attributes['path']) end; end;} end; |
Re: Ideen für spezielle Stringbearbeitung
Moin,
kennst du keine Möglichkeiten einen Fehler einzugrenzen? Versuche es mal so:
Delphi-Quellcode:
Freundliche Grüße
function CreateDocument(var doc: IXMLDOMDocument2; const markup: string): Boolean;
begin doc := ComsDOMDocument.Create; doc.async := False; Result := doc.loadXML(markup); end; procedure ShowParseError(pe: IXMLDOMParseError); const FMT = 'line %d, linepos %d'#13'%s'#13#13'%s'; begin with pe do ShowMessage(Format(FMT, [line, linepos, reason, Copy(srctext, 1, linepos)])); end; procedure Tfrmxml.Button1Click(Sender: TObject); const XPATH = '//Basket[%d]/@path'; var doc: IXMLDOMDocument2; n: IXMLDOMNode; begin if CreateDocument(doc, Memo1.Text) then begin n := doc.selectSingleNode(Format(XPATH, [1])); ShowMessage(VarToStr(n.nodeValue)); end else ShowParseError(doc.parseError); end; |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
Sonst wär ich wohl nicht hier im Forum drin... |
Re: Ideen für spezielle Stringbearbeitung
line 5, linepos 70
An dieser Stelle sind keine Leerzeichen zugelassen. oldIniSettingsForDW="[bibl_00995018.184_RESULT]#xD;#xA;COLFIXED=0# hab den String jetzt extra hier nochmal von Hand eingegeben und ich kann wirklich kein Leerzeichen entdecken. |
Re: Ideen für spezielle Stringbearbeitung
Du interpretierst die übersetzte Fehlermeldung falsch - mit Leerzeichen ist white space gemeint und dazu zählen auch die kodierten Zeilenumbrüche.
Dein Fehler tritt bei mir nicht auf, weil ich mit MSXML4 getestet habe, du aber wohl MSXML6 benutzt. |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
hab ich mal so gemacht und bekomm wieder die selbe Meldung. |
Re: Ideen für spezielle Stringbearbeitung
So kommen wir nicht weiter.
Mach bitte eine kleine Demo fertig, erstelle ein ZIP-Archiv der Quellen und hänge das hier rein. Ich schaue mir das dann an. |
Re: Ideen für spezielle Stringbearbeitung
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
|
Re: Ideen für spezielle Stringbearbeitung
Hallo,
versuche es mal so:
Delphi-Quellcode:
Weil du beim Memo die property Wrap auf True gesetzt hast, wird der Text umgebrochen - leider aber nach Regeln, die der XML-Parser nicht mag.
function CreateDocumentFromUrl(var doc: IXMLDOMDocument2; const url: string): Boolean;
begin doc := ComsDOMDocument.Create; doc.async := False; Result := doc.load(url); end; { ... } procedure Tfrmxml.Button1Click(Sender: TObject); const XPATH = '//Basket[%d]/@path'; var doc: IXMLDOMDocument2; n: IXMLDOMNode; begin if CreateDocumentFromUrl(doc, 'beispiel.xml') then begin n := doc.selectSingleNode(Format(XPATH, [1])); ShowMessage(VarToStr(n.nodeValue)); end else ShowParseError(doc.parseError); end; Hättest du Wrap auf False gesetzt (default), dann wäre dir der zwangsweise Umbruch nach 1024 Zeichen pro Zeile (editor limitation) zum Verhängnis geworden, da wahrscheinlich wieder an einer für den XML-Parser nicht akzeptablen Stelle umgebrochen worden wäre. Entweder du liest das Dokument erst zur Laufzeit in dein Memo ein, oder - wenn du das Memo nicht zur Visualisierung benötigst - du lässt das XML-Dokument gleich vom Parser lesen, wie ich es mit CreateDocumentFromUrl() zeige. Freundliche Grüße |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
Ich kann jetzt zumindest schon mal den Pfad einlesen. Jetzt muss ich noch gucken wie ich den modifiziere bzw. neuanlege..... (?) dankevielmals für die geduldige hilfe bis dahin :) |
Re: Ideen für spezielle Stringbearbeitung
ich hab das ganze jetzt so gemacht:
Delphi-Quellcode:
dbmemo1 ist eine dbmemo welche ich direkt aus der db abfülle. soweit so gut. aber wo kann ich den kosmischen XML code //baskets[%d] usw. lernen? ich möchte nämlich jetzt im zweiten schritt den wert: Baskets totalNumber auslesen. So wie ich es oben gemacht habe scheint es nicht zu stimmen, ich krieg eine Zugriffsverletzung. was mach ich falsch?
procedure Tfrmxml.btnanzClick(Sender: TObject);
const XPATH = '//Basket[%d]/@path'; XANZAHL = '//Baskets[%d]/@totalNumber'; var doc: IXMLDOMDocument2; n: IXMLDOMNode; begin // Anzahl Briefkörbe auslesen if CreateDocument(doc, dbMemo1.Text) then begin n := doc.selectSingleNode(Format(XANZAHL, [1])); edanzahl.text:=(VarToStr(n.nodeValue)); end else ShowParseError(doc.parseError); // Briefkorb Pfad auslesen if CreateDocument(doc, dbMemo1.Text) then begin n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)])); edpfad.text:=(VarToStr(n.nodeValue)); end else ShowParseError(doc.parseError); { if CreateDocumentFromUrl(doc, 'beispiel.xml') then begin n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)])); edpfad.text:=(VarToStr(n.nodeValue)); end else ShowParseError(doc.parseError);} end; bin weitergekommen. Und zwar hab ich das %d weggelassen bei der Definition von XANZAHL. Ich versteh zwar nicht warum (was bedeutet dieses %d???). kannst du mir noch sagen wie ich jetzt den mutierten Wert aus edpfad.text wieder in den XML String speichere? Ich dachte evl. mit: n.nodeValue:=edpfad.text? Aber wie krieg ich den geänderten Node dann in den XML rein? |
Re: Ideen für spezielle Stringbearbeitung
Hallo,
du solltest den XML Code nur einmal laden:
Delphi-Quellcode:
Das Verändern des Pfades hatte ich dir bereits in Beitrag #39 gezeigt. An den aktuellen XML Code gelangst du über doc.xml, was ich dir im gleichen Beitrag auch gezeigt habe. %d ist ein sogenannter format specifier und du findest diese im Help Topic "Format-Strings" beschrieben. Nach Ersetzung der Platzhalter durch die Funktion Format() erhältst du einen sogenannten XPATH-Ausdruck. XPATH ist eine W3-Spezifikation zur genauen Lokalisierung von Objekten in einem XML Document Object Model (XML DOM).
procedure Tfrmxml.btnanzClick(Sender: TObject);
const XPATH = '//Basket[%d]/@path'; XANZAHL = '//Baskets[%d]/@totalNumber'; var doc: IXMLDOMDocument2; n: IXMLDOMNode; begin if CreateDocument(doc, dbMemo1.Text) then begin // Anzahl Briefkörbe auslesen n := doc.selectSingleNode(Format(XANZAHL, [1])); edanzahl.text:=(VarToStr(n.nodeValue)); // Briefkorb Pfad auslesen n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)])); edpfad.text:=(VarToStr(n.nodeValue)); end else ShowParseError(doc.parseError); end; Freundliche Grüße |
Re: Ideen für spezielle Stringbearbeitung
du hast Recht marabu. Sorry hab mir das nochmals vor Augen geführt und umgesetzt:
Definition der SQL Statements:
Delphi-Quellcode:
Prozedur:
unit mySQLstatements;
interface uses Windows, myGlobals, nsa_spezial; const sql_read_benutzer: string = 'SELECT iid, domain, user_account from DWWinUserID'; sql_read_briefkorb: string = 'SELECT name, password, guid, settings, active from DWUser where name = $benutzername'; sql_update_xml: string = 'UPDATE DWUser set settings = $xml where name = $benutzername';
Delphi-Quellcode:
Parameter object is improperly defined. Inconsistent or incomplete information was provided.
procedure Tfrmxml.edmutClick(Sender: TObject);
const XPATH = '//Basket[%d]/@path'; XANZAHL = '//Baskets/@totalNumber'; var doc: IXMLDOMDocument2; n: IXMLDOMNode; sqltext:string; s:string; begin s:=chr(39); // Hochkomma // Briefkorb Pfad speichern if CreateDocument(doc, dbMemo1.Text) then begin n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)-1])); n.nodeValue:=(edpfad.text); sqltext:=stringreplace(sql_update_xml,'$benutzername',s+edbenutzername.text+s,[rfIgnoreCase]); sqltext:=stringreplace(sqltext,'$xml',s+doc.xml+s,[rfIgnoreCase]); datamodule2005.ADOQuery3.SQL.Text:=sqltext; datamodule2005.ADOQuery3.ExecSQL; showmessage(sqltext); //edpfad.text:=(VarToStr(n.nodeValue)); end else ShowParseError(doc.parseError); end; Kann nix mit der Meldung anfangen. Hab ich was vergessen? |
Re: Ideen für spezielle Stringbearbeitung
Hallo,
du hast vergessen die Stelle zu bezeichnen, an der der Fehler auftritt. Außerdem scheint es so, als ob du versuchst ein feature der ADO-Komponenten nachzubilden: Parameter. Statt des Dollarzeichens verwendest du dann einen Doppelpunkt:
Delphi-Quellcode:
Die durch den Doppelpunkt markierten Parameter werden dir in der Eigenschaft Params einer DataSet-Komponente zur Manipulation angeboten. Ein Beispiel von vielen zum Umgang mit Params findest du z.B. hier:
const
SQL_SEL_ACCTS = 'SELECT iid, domain, user_account ' + 'FROM DWWinUserID ' ; SQL_SEL_USER = 'SELECT name, password, guid, settings, active ' + 'FROM DWUser WHERE name = :benutzername ' ; SQL_UPD = 'UPDATE DWUser SET settings = :xml ' + 'WHERE name = :benutzername ' ; ![]() In deinem konkreten Fall könnte der XML Parser direkt aus einem BlobStream lesen und dort auch wieder hin schreiben. Dabei könnten dir die Funktionen ![]() ![]() BTW: "name" ist kein besonders gut gewählter Name für eine Spalte. Freundliche Grüße |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
Hey Der Fehler tritt im Ausführungsmoment auf (ExecSQL). Ich befürchte der XML String ist zu lang um den in einen SQL Update einzubetten. Ist das möglich? Wie ich ADO Parameter verwende weiss ich und verwend ich auch ab und zu. Aber nicht in diesem Fall wo es sich um ein einfaches Projekt handelt. So ist diese Lösung für mich die einfachere und naheliegendere. Den Spaltennamen "name" ist nicht nach meinem Wunsch so getauft worden. Dies hat die Herstellerfirma der Software so gemacht und ist somit nicht in meinem Einflussbereich. Ich muss damit arbeiten obs schlau ist oder nicht. |
Re: Ideen für spezielle Stringbearbeitung
Erfolgserlebnis:
Delphi-Quellcode:
Danke für den Tipp marabu. Mithilfe von Parametern scheint sich das Problem in Luft aufgelöst zu haben. Ist mir zwar nicht klar warum, aber ok.
procedure Tfrmxml.btnmutClick(Sender: TObject);
const XPATH = '//Basket[%d]/@path'; XANZAHL = '//Baskets/@totalNumber'; var doc: IXMLDOMDocument2; n: IXMLDOMNode; sqltext:string; s:string; begin s:=chr(39); // Hochkomma // Briefkorb Pfad speichern if CreateDocument(doc, dbMemo1.Text) then begin n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)-1])); n.nodeValue:=(edpfad.text); // sqltext:=stringreplace(sql_update_xml,'$benutzername',s+edbenutzername.text+s,[rfIgnoreCase]); // sqltext:=stringreplace(sqltext,'$xml',s+doc.xml+s,[rfIgnoreCase]); datamodule2005.ADOQuery3.SQL.Text:=sql_update_xml; datamodule2005.ADOQuery3.Parameters.ParamByName('xml').Value:=doc.xml; datamodule2005.ADOQuery3.Parameters.ParamByName('benutzername').Value:=edbenutzername.text; showmessage(datamodule2005.ADOQuery3.SQL.Text); datamodule2005.ADOQuery3.ExecSQL; end else ShowParseError(doc.parseError); end; Was ich noch ändern musste: doc.xml verwenden und nicht in Hochkomma in die DB setzen. |
Re: Ideen für spezielle Stringbearbeitung
Bei mir ist jetzt noch die Frage aufgetaucht:
Wenn ein Benutzer keinen Basket im XML definiert hat (totalNumber=0). Wie kann ich diesen dann eintragen/speichern/eröffnen? Hast du da ein Beispiel? Das wäre noch das Tüpfli auf dem i - wie wir in der CH sagen :) |
Re: Ideen für spezielle Stringbearbeitung
Sali,
luegsch emal:
Delphi-Quellcode:
Tschüss
procedure AddBasket(doc: IXMLDOMDocument2; const path, opened, isUserAssigned: string);
const xpBaskets = '//Baskets'; tagBasket = 'Basket'; atPath = 'path'; atOpened = 'opened'; atIsUserAssigned = 'isUserAssigned'; var e: IXMLDOMElement; begin e := doc.selectSingleNode(xpBaskets) as IXMLDOMElement; if Assigned(e) then with e.appendChild(doc.createElement(tagBasket)) as IXMLDOMElement do begin setAttribute(atPath, path); setAttribute(atOpened, opened); setAttribute(atIsUserAssigned, isUserAssigned); end; end; |
Re: Ideen für spezielle Stringbearbeitung
Zitat:
scheinbar hab ich wieder was missverstanden oder falsch gemacht. denn es passiert gar nix. habe es folgendermassen in einer prozedur verpackt:
Delphi-Quellcode:
wie gesagt, wird leider nichts gespeichert. wahrscheinlich wieder eine kleine sache??
procedure Tfrmxml.btnneubClick(Sender: TObject);
var doc: IXMLDOMDocument2; begin if CreateDocument(doc, dbMemo1.Text) then begin AddBasket(doc,edpfad.text,'true','true'); datamodule2005.ADOQuery3.SQL.Text:=sql_update_xml; datamodule2005.ADOQuery3.Parameters.ParamByName('xml').Value:=doc.xml; datamodule2005.ADOQuery3.Parameters.ParamByName('benutzername').Value:=edbenutzername.text; datamodule2005.ADOQuery3.ExecSQL; btnneu.click; // Neu! end else ShowParseError(doc.parseError); end; |
Re: Ideen für spezielle Stringbearbeitung
XML to String.
Gibts sowas eigentlich? Bzw. doc (IXMLDOMDocument2) to String. doc.xml... mensch ist wohl schon spät. sorry |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:21 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz