Forum > Generale

XML - esiste un modo per leggere una riga alla volta

(1/1)

Maverich:
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


--- Codice: ---
     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;


--- Termina codice ---

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


--- Codice: ---
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;     

--- Termina codice ---

nomorelogic:
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 :

--- Codice: ---
StringReplace(sTesto, '***CognomeNome***', 'Pippo', [rfReplaceAll,rfIgnoreCase])

--- Termina codice ---

o, se proprio vuoi usare la Pos, qualcosa tipo:

--- Codice: ---
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);

--- Termina codice ---

Stilgar:
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
--- Codice: ---
//text()=="***CognomeNome***"
--- Termina codice ---
(Fatta al volo, non verificata ;) ) Per tarare le espressioni regolari per xpath utilizzo un plug per FF. (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 ;)

Stilgar:
Allora, ho usato Word 2010.

da TXMLDocument, chiedi i nodi (getElementsByTagName) "text:p"
In questo modo hai tutti i "paragrafi".
Modifichi il textContent di questi nodi.

Navigazione

[0] Indice dei post

Vai alla versione completa