У меня есть функция для записи значения в нод. | Код | procedure TXmlClass.Write(Path: string; Key: string; Value: string); var Node: IXMLNode; ts: TStringList; i: integer; begin ts := TStringList.Create; ts.Delimiter := '\'; ts.DelimitedText := Path; Node := XMLDoc.DocumentElement; if Node.ChildNodes.IndexOf(ts[0]) < 0 then Node := Node.AddChild(ts[0]) else Node := Node.ChildNodes.FindNode(ts[0]); for I := 1 to ts.Count - 1 do begin if Node.ChildNodes.IndexOf(ts[i]) < 0 then Node := Node.AddChild(ts[i]) else Node := Node.ChildNodes.FindNode(ts[i]); end; if Node.ChildNodes.IndexOf(Key) < 0 then Node := Node.AddChild(Key) else Node := Node.ChildNodes.FindNode(Key); Node.Text := Value; ts.Free; end;
|
Появилась необходимость написать её так, чтоб можно было ходить по разным веткам, с разными аттрибутами. Например: | Код | - <Internal> - <DF id="D000"> <EF id="D002">333232363538343836</EF> </DF> - <DF id="FF00"> <EF id="F002">615B5F1F58503C55544F504554524F563C564F444B494E3C3C4956414E3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3332323635383438363255544F373831323131324D313031323133383C3C3C3C3C3C3C3C3C3C3C3C3C3C3032</EF> </DF> - <DF id="E000"> <EF id="E040">5E7BA37C10DDC479654BFE217C855A9924FF621BD7763696C3DEDCFA60EBFB6FA918120824200AFE3F60A89443E4EE9185FA91F0C727F38BE807B1C2C0449F04</EF> <EF id="E041">308201633081FFA003020100020A0302030405060708090A301C06062A8503020203301206072A85030202230106072A850302021E013020311E301C06035504031315536174696E20434120636572746966696361746500301E170D3035303130313030303030305A170D3038303130313030303030305A3027312530230603550403131C536174696E20706572736F6E616C20636572746966696361746533003063301C06062A8503020213301206072A85030202230106072A850302021E010343020440E970AB6531E7DDB661D95A61DA2345D23C26F46A91EEF0F27A6B52F638F6BA1C716FCE1778DB0A4EE1F5954F0142F017E1C915FBF1F91C0F2A9746B66A2A9DF4301C06062A8503020203301206072A85030202230106072A850302021E01034100691BA75C6C71C68206FD8A72CBF4FA8D608151D5C9522DCA4A751BDF4CF97F15CFE9C0BB3BC77A59D4F928F83295303F8F01917DB4097FDA8A867017BF655EBD</EF> </DF> </Internal>
|
Обычно я писал вот так: | Код | x.Write('Query\Passport\Chip\Internal\DF', 'EF', 'test');
|
Но сейчас написал новую функцию для записи с аттрибутами, которые указываются через символ ":" (двоеточие) Функция выглядит так: | Код | procedure TXMLClass.WriteAttr(Path, Key, Value: string); var Node: IXMLNode; tmp, ts, KV: TStringList; i, c: integer; begin ts := TStringList.Create; tmp := TStringList.Create; KV := TStringList.Create; tmp.Delimiter := '\'; tmp.DelimitedText := Path; for i := 0 to tmp.Count - 1 do begin if Pos(':', tmp[i]) > 0 then begin KV.Add(Copy(tmp[i], Pos(':', tmp[i]) + 1, Length(tmp[i]))); ts.Add(Copy(tmp[i], 1, (Pos(':', tmp[i])) - 1)); end else begin KV.Add('-'); ts.Add(tmp[i]); end; end; Node := XMLDoc.DocumentElement; c := 0; repeat if Node.ChildNodes.IndexOf(ts[0]) < 0 then Node := Node.AddChild(ts[0]) else Node := Node.ChildNodes.FindNode(ts[0]); if KV[0] = '-' then break else if Node.Attributes[KV.Names[0]] = KV.Values[KV.Names[0]] then break; Inc(c); until c > 10; c := 0; for I := 1 to ts.Count - 1 do begin repeat if Node.ChildNodes.IndexOf(ts[i]) < 0 then Node := Node.AddChild(ts[i]) else Node := Node.ChildNodes.FindNode(ts[i]); if KV[i] = '-' then break else if Node.Attributes[KV.Names[i]] = KV.Values[KV.Names[i]] then break else Node.NextSibling; Inc(c); until c > 10; end; c := 0; KV.Clear; if Pos(':', Key) > 0 then begin KV.Add(Copy(Key, Pos(':', Key) + 1, Length(Key))); end else KV.Add('-'); repeat if Node.ChildNodes.IndexOf(Key) < 0 then Node := Node.AddChild(Key) else Node := Node.ChildNodes.FindNode(Key); if KV[0] = ' ' then break else if Node.Attributes[KV.Names[0]] = KV.Values[KV.Names[0]] then break; Inc(c); until c > 10; Node.Text := Value; tmp.Free; ts.Free; KV.Free; end;
|
Но функция постоянно теряет нужный нод. Она встаёт на нод <DF id="D000"> и никак не желает переходить на <DF id="FF00">. Сейчас вызов функции выглядит так: | Код | x.WriteAttr('Query\Passport\Chip\Internal\DF:id=E000', 'EF:id=E040', 'test');
|
Прошу помощи. Собственно основная сложность вот в этом цикле: | Код | for I := 1 to ts.Count - 1 do begin repeat if Node.ChildNodes.IndexOf(ts[i]) < 0 then Node := Node.AddChild(ts[i]) else Node := Node.ChildNodes.FindNode(ts[i]); if KV[i] = '-' then break else if Node.Attributes[KV.Names[i]] = KV.Values[KV.Names[i]] then break else Node.NextSibling; Inc(c); until c > 10; end;
|
Это сообщение отредактировал(а) iddqd - 9.3.2007, 12:55
|