Копировать и копировать неправильно работает со списком строк
Я получил большой XML-файл, и я хочу сохранить каждый идентификатор, источник и цель в списке строк для генерации после успешного импорта в списки строк построить запрос к MySQL.
Вот фрагмент моего XML:
xliff version="1.1">
<file original="Xliff Demo" source-language="EN" target-language="DE" datatype="html">
<header>
<skl>
<external-file uid="017dbcf0-c82c-11e2-ba2b-005056c00008" href="skl\simple.htm.skl"/>
</skl>
</header>
<body>
<trans-unit id="00ffmnpB5wBV5KFqBxuHLi4fwJvvuB">
<source xml:lang="EN">1lnRUfBBeHtbS96uULSht42VNMN7XE4qt9JrOcWhtoTuhnbAQ9</source>
<target xml:lang="DE">zZvOLJfLCy9oP5GQYfEqw5LAeC2ESAxRmVe1JyQdmJ1eG2jz1N</target>
<note/></trans-unit>
<trans-unit id="00kjUwy1rJ54bEGYp7XZvtBiY32pmj">
<source xml:lang="EN">HXOQLUWkfJg206vRw8lyWhCWChOacVxbMukfQ0HUdNHSI18GG4</source>
<target xml:lang="DE">8dsX38mezeZ0w0w37LI66CDRuI8gBD23zT5KR4iqYNv3IGUgH0</target>
<note/></trans-unit>
<trans-unit id="00kk3Af8SFpHyelAaYrgK58b9GbIDj">
<source xml:lang="EN">wQFxZiCiRsSNWs20G4WXAmDBRdRL6fcrrJnCgtbiXGSfHzpYrT</source>
<target xml:lang="DE">oFVTUdPkExOhISYofIImLsnVKd3NSZg32tyeP5iRxRZdmuYQDy</target>
<note/></trans-unit>
<trans-unit id="00Ky2dmDU9wGTWBnJxeL9b9gkts5UQ">
<source xml:lang="EN">nHQcjAW02lWe0SyOhqGtyqUhpwQ8qgWX3rUynMRf4BDHfVdHOC</source>
<target xml:lang="DE">0CURp1dcZydB1V2rEZ1lnOhmYufOYbrLbh84e1ZnALlzZPVq4F</target>
<note/></trans-unit>
<trans-unit id="00pMSFlBfA3bJ8Xy9I78wz6XisPYcV">
<source xml:lang="EN">IuhtaVnZtF67nxKz5dbmuy8BEMTs2X1120FzDtIplKF2Me5AsQ</source>
<target xml:lang="DE">1BGSJQDZBm4UW974pucnX3XHuYOQYpC7nTcIH01rbKlOkVi9bo</target>
<note/></trans-unit>
<trans-unit id="012w2kb2d1Lo6NbJLE0BawThzsSuCJ">
<source xml:lang="EN">0RoniOGZ7V7WTF1YQg59B8jBhRxnLVXscC1LOGPzKPYRs76oIz</source>
<target xml:lang="DE">gyw15fkHTni2aUGWI5qiPHEz8vsJJJsW4OOqKwGYL1qzfUVfLO</target>
<note/></trans-unit>
...
..
..
Поэтому я пытаюсь сохранить каждую запись идентификатора транс-единицы, источника xml:lang"EN", цели xml:lang="DE" в отдельном списке строк, но только значения.
Вот мой код:
{ ----------- Import Procedure ------------ }
procedure TForm2.Button2Click(Sender: TObject);
var
xmlFile, idList, sourceList, targetList: TStringList; // StringListe wo die Xml Datei eingelesen wird
i: Integer;
id, source, target: String;
idTmp, idTmp2, sourceTmp, sourceTmp2, targetTmp, targetTmp2: Integer;
begin
try
xmlFile := TStringList.Create;
idList := TStringList.Create;
sourceList := TStringList.Create;
targetList := TStringList.Create;
if OpenDialog1.Execute then
xmlFile.LoadFromFile(OpenDialog1.FileName);
{Debug}
//ShowMessage(IntToStr(XmlFile.Count)); Ausgabe der Zeilenlänge
//ShowMessage(XmlFile[8]); // Ausgabe der Zeile 8
{/Debug}
for i := 0 to xmlFile.Count-1 do // Über alle Zeilen der StringList gehen und folgendes tun:
begin // Code pro Zeile
{id}
idTmp := Pos('<trans-unit id="', xmlFile.Strings[i])+16; // Sucht nach trans-unit id (16 ist die Anzahl der Länge vom Suchstring in dem Fall trans-unit id 16 Stellen lang
if idTmp > 5 then // Überprüfen ob was gefunden wurde (Ungleich 0)
begin
idTmp2 := Pos('"', xmlFile.Strings[i], idTmp); // Ermittelt die Position vom Ende des Strings (")
idList.Add(Copy(xmlFile.Strings[i], idTmp, idTmp2-idTmp));
end;
{source}
sourceTmp := Pos('<source xml:lang="EN">', xmlFile.Strings[i])+22;
if sourceTmp > 5 then // Überprüfen ob was gefunden wurde (Ungleich 0)
begin
sourceTmp2 := Pos('<', xmlFile.Strings[i], sourceTmp); // Ermittelt die Position vom Ende des Strings (")
sourceList.Add(Copy(xmlFile.Strings[i], sourceTmp, sourceTmp2-sourceTmp));
end;
{target}
targetTmp := Pos('<target xml:lang="DE">', xmlFile.Strings[i])+22;
if targetTmp > 5 then // Überprüfen ob was gefunden wurde (Ungleich 0)
begin
targetTmp2 := Pos('<', xmlFile.Strings[i], targetTmp); // Ermittelt die Position vom Ende des Strings (")
targetList.Add(Copy(xmlFile.Strings[i], targetTmp, targetTmp2-targetTmp));
end;
end;
StartPerformance;
UniConnection1.Open;
finally
ListBox1.items.assign(idList);
ListBox2.items.assign(sourceList);
ListBox3.items.assign(targetList);
ShowMessage('Import in StringListen fertiggestellt.');
xmlFile.Free;
idList.Free;
sourceList.Free;;
targetList.Free;
end;
end;
Но это не работает так, как я хочу. Моя проблема в том, что он также сохраняет пустые строки в списке строк и прочем мусоре. Я действительно не нахожу свою ошибку, и я впервые использую эту функцию копирования / размещения.
Вот скриншот
Что я должен изменить, чтобы исправить мою проблему и сохранить только правильные строки в моих 3 списках строк?
2 ответа
Вот:
idTmp := Pos('<trans-unit id="', xmlFile.Strings[i])+16;
if idTmp > 5 then
...
idTmp
всегда будет больше 5 - вы добавляете 16 к нему независимо от того, что и он всегда возвращает положительное значение (или ноль, если нет совпадения).
Самое простое изменение здесь будет:
idTmp := Pos('<trans-unit id="', xmlFile.Strings[i]);
if idTmp > 0 then begin //Pos returns 0 if no match found
idTmp := idTmp + 16;
idTmp2 := PosEx('"', xmlFile.Strings[i], idTmp);
idList.Add(Copy(xmlFile.Strings[i], idTmp, idTmp2-idTmp));
end;
Изменение для двух других блоков будет следовать аналогичным образом.
Вы заметите, что я использовал StrUtils.PosEx здесь для idTmp2
- Я не знаю, как ваш код скомпилирован с использованием Pos для второй функции...
редактировать
Хорошо, похоже, что Pos был изменен в XE3 для включения смещенных перегрузок. Если ваша цель здесь - производительность (как это видно из комментариев), вы, вероятно, должны прочитать это:
http://qc.embarcadero.com/wc/qcmain.aspx?d=111103
Кроме того, что, я думаю, очень важно, это действительно ужасный способ разбора XML. Я настоятельно рекомендую вам прочитать некоторые исходные коды из проектов, которые уже делают это, чтобы лучше понять, как вы должны подходить к проблеме. Некоторые примеры могут быть:
Возможно, вам следует подумать об использовании интерфейса IXMLDocument для загрузки XML-файла в структуру данных и последующего заполнения ваших списков строк.
Пример был размещен здесь: /questions/22734602/kak-sozdat-etot-xml-s-delphi/22734625#22734625