mi trovo a voler leggere un XML riga per riga (come un normale file testo), e sotituire le stringhe usate come identificatore (es: testo ***CognomeNome*** testo).
ho preso come riferimento un testo Libre/OpenOffice (file content.xml)
il problema e' che seguendo questa logica
b := true;
repeat
begin
ReadLn(F, sTesto); //legge riga F: TextFile
repeat
//ricerca identificatore
i := Pos('***CognomeNome***', sTesto);
if i > 0 then
begin
Memo1.Lines.Add(sTesto);
sModificato := Replace(sTesto, '***CognomeNome***', 'Pippo');
b := False;
end
else b := True;
until b;
end;
until eof(F);
....
function TForm1.Replace(Dest, SubStr, Str: string): string;
var iPosition: Integer;
begin
iPosition:=Pos(SubStr, Dest);
Delete(Dest, iPosition, Length(SubStr));
Insert(Str, Dest, iPosition);
Result:=Dest;
end;
ottengo una stringa lunga
1^ riga .... trova il carattere equivalente alla nuova riga <?xml version="1.0" encoding="UTF-8"?>
2^ riga tutto il resto del documento (trova il carattere equivalente alla nuova riga solo alla fine del documento)
cosi' facendo trovo solo il primo identificatore, e per trovare i successivi devo
sovrascrivere il file XML Chiudere e Riaprire.
ho provato anche la unit XMLRead, ma TextContents equivale al ReadLn su un TextFile
procedure TForm1.Button4Click(Sender: TObject);
var F: TextFile;
sTesto, sModificato: string;
i, j : integer;
Documento: TXMLDocument;
Child: TDOMNode;
b: boolean;
begin
ReadXMLFile(Documento, 'E:\Lazarus\TestZip2\content.xml');
Memo1.Lines.Clear;
// using FirstChild and NextSibling properties
Child := Documento.DocumentElement.FirstChild;
while Assigned(Child) do
begin
Memo1.Lines.Add(Child.TextContent);
//Memo1.Lines.Add(Child.NodeValue);
//Memo1.Lines.Add(Child.Attributes.Item[0].NodeValue);
//Child.Attributes.Item[0].NodeValue
// using ChildNodes method
with Child.ChildNodes do
try
for j := 0 to (Count - 1) do
begin
//Memo1.Lines.Add(Item[j].NodeName); // + ' ' + Item[j].FirstChild.NodeValue);
Memo2.LInes.Clear;
Memo2.Lines.Add(Item[j].TextContent);
end;
finally
Free;
end;
Child := Child.NextSibling;
end;
Documento.Free;
end;
probabilmente il carattere di CR+FL lo trovi solamente alla fine della prima riga ed alla fine del file.
prova ad aprire il file originale con un normale editor di testo e togli "a capo automatico" dall impostazioni, molto probabilmente vedrai 2 sole righe. in
alternativa, se le righe sono più di 2, aprilo in modalità esadecimale, magari gli "a capo" sono dei semplici LF mentre ReadLn cerca CR+FL (almeno mi pare di ricordare :)).
comunque non credo sia un problema il numero delle righe :)
in alternativa a Pos, per fare tutto il lavoro in un colpo solo, potresti usare :
StringReplace(sTesto, '***CognomeNome***', 'Pippo', [rfReplaceAll,rfIgnoreCase])
o, se proprio vuoi usare la Pos, qualcosa tipo:
sModificato:=sTesto;
i := Pos('***CognomeNome***', sModificato);
while i > 0 do
begin
sModificato := Replace(sModificato, '***CognomeNome***', 'Pippo');
i := Pos('***CognomeNome***', sModificato);
end;
Memo1.Lines.Add(sModificato);
Se fornisci un content.xml di riferimento diventa più semplice aiutarti a tarare un algoritmo ;)
cmq. Se chiedi il risultato documentElement.textContent, viene utilizzato tutto l'albero per comporre la stringa.
Quello che dovresti fare è identificare il nodo che contiene quello che ti interessa.
Con XPATH diventa qualche cosa del tipo "text()==xxx" per ottenere i nodi.
L'implementazione che viene fornita con Lazarus/FPC, non è un fulmine di guerra, ma lavora bene.
Se devi puntare a 100 elementi, va un pochino in crisi ;)
Una possibile richiesta XPATH dovrebbe essere del tipo //text()=="***CognomeNome***"
(Fatta al volo, non verificata ;) ) Per tarare le espressioni regolari per xpath utilizzo un plug per FF. (http://code.google.com/p/xpathchecker/ (http://code.google.com/p/xpathchecker/))
EDIT:
PS1: Tutti i padri con textContent includono il testo dei figli.
PS2: http://www.freepascal.org/docs-html/rtl/sysutils/stringreplace.html Cambia funzione per la sostituzione di tutte le occorenze ;)