Вопрос Работа с XML в Inno

LagunaFAN

Мимокрокодил
Доброй ночи!

Появилась необходимость работы с xml для скрипта. Пытаюсь адаптировать свой инсталл для установки в Origin.

Задача стоит такая. Есть файл local.xml, из которого нужно прочитать значение аттрибута value (см. ниже, value="N:\Games\Origin Games\"), длина которого может меняться, а затем это значение вывести в строку выбора директории на соответствующей странице инсталлятора. Иначе, если файла не существует, вывести MsgBox с сообщением, что клиент не установлен. Но структура у этого файла необычная. Нашел тут модуль для работы с XML, но он работает с тегами, как я понял, имеющими закрывающий тег и значениями в них. А тут, закрывающего тега нет и есть аттрибуты :(

Код:
<?xml version="1.0"?>
<Settings>
  <Setting value="N:\Games\Origin\DownloadCache\Cache" key="CacheDir" type="10"/>
  <Setting value="false" key="CacheDirRemoval" type="1"/>
  <Setting value="N:\Games\Origin Games\" key="DownloadInPlaceDir" type="10"/>
</Settings>
Возможно ли такое осуществить в рамках Inno? Пожалуйста, помогите :(
 
Последнее редактирование:

LagunaFAN

Мимокрокодил
nik1967, спасибо за пример, попробовал. Вся проблема в том, что во всем документе, как видно, у меня повторяется один и тот же параметр <Setting .... </>, с одним и тем же набором атрибутов, но с разными значениями. А так как он один и тот же, то при использовании примера, ссылку на который вы дали, скрипт находит значение самого верхнего и первого по списку атрибута, но мне надо получить значение третьего по списку (двумя строками ниже, а именно здесь - <Setting value="N:\Games\Origin Games\" key="DownloadInPlaceDir" type="10"/>) :(

Можно ли как-то сделать, чтобы поиск производился на определенной строке? Прошу прощения. Я в секции CODE не особо шарю. Какие-то простые вещи сделать могу, но это выше моих сил. Поэтому прошу помощи.
 
Последнее редактирование:

nik1967

Old Men
Проверенный
LagunaFAN,
Код:
[Setup]
Appname=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp
OutputDir=.

[code] 
function GetValue(strFilename,keyFind: string; var tvalue: string): string;
var
  i,vPos: Integer;
  strArr: TArrayOfString;
begin
  LoadStringsFromFile(strFilename, strArr);
  for i:= 0 to GetArrayLength(strArr)-1 do begin
  if Pos(keyFind,strArr[i])>0 then begin
  vPos:= Pos(keyFind,strArr[i]);
  Delete(strArr[i],1,vPos-25);
  Delete(strArr[i],Pos('"',strArr[i]),Length(strArr[i]));
  tvalue:= strArr[i];
  Result:= tvalue;
  end;
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
var
   S: string;
begin
   case CurPageID of
     wpSelectDir: begin
       if FileExists(ExpandConstant('{src}\local.xml')) then begin
         GetValue(ExpandConstant('{src}\local.xml'), 'key="DownloadInPlaceDir"', S);
         WizardForm.DirEdit.Text:= S;
       end else MsgBox('Клиент не установлен', mbInformation, MB_OK);
     end;
   end;
end;
Правда, это при условии, что key="DownloadInPlaceDir" меняться не будет. Поиск у меня построен на этом параметре.
 

LagunaFAN

Мимокрокодил
nik1967, скрипту удается сделать выборку из нужной строки в поле с директорией, но итоговый результат, как я понимаю, получается зависим от длины значения value или от какой-то другой длины. То есть, допустим, если значение пустое ( setting value="" ), то поле с выбором директории вижу <setting value=. Если значение N:\Games, то вижу tting value=. А если значение делаю таким, как в шапке темы, то в итоге поле вообще остается пустым. Изменил vPos на -24, тем самым заставил таки вывести в поле с директорией значение как в шапке, но и тут чем длиннее значение, тем слева короче оно в итоге в поле. А чем короче значение в xml-файле, тем дальше смещается влево.

Выбрать значение целиком независимо от длины значит заставить его нельзя? :(
 
Последнее редактирование:

nik1967

Old Men
Проверенный
LagunaFAN,
Код:
[Setup]
Appname=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp
OutputDir=.

[code] 
function GetValue(strFilename,keyFind: string; var tvalue: string): string;
var
  s: String;
  i: Integer;
  strArr: TArrayOfString;
begin
  LoadStringsFromFile(strFilename, strArr);
  for i:= 0 to GetArrayLength(strArr)-1 do begin
     if Pos(keyFind,strArr[i])>0 then begin
       S:= Copy(strArr[i],Pos('"',strArr[i])+1,Length(strArr[i]));
         Delete(S,Pos('"',S),Length(strArr[i]));
         tvalue:= S;
       Result:= tvalue;
     end;
   end;
end;

procedure CurPageChanged(CurPageID: Integer);
var
   St: string;
begin
   case CurPageID of
     wpSelectDir: begin
       if FileExists(ExpandConstant('{src}\local.xml')) then begin
         GetValue(ExpandConstant('{src}\local.xml'), 'key="DownloadInPlaceDir"', St);
         WizardForm.DirEdit.Text:= St;
       end else MsgBox('Клиент не установлен', mbInformation, MB_OK);
     end;
   end;
end;
 
Последнее редактирование:

LagunaFAN

Мимокрокодил
nik1967, Искренне благодарю за помощь! Заработало! :drinks::yahoo:

А можно как то сделать функцию проверки на наличие атрибута key="DownloadInPlaceDir"? У меня есть мысли как можно было эту функцию применить в случаях, если атрибут отсутствует. Но как сделать саму функцию я не знаю :(
 
Последнее редактирование:

sergey3695

Ветеран
Модератор
LagunaFAN, Да тут как-то и из скрипта выше выдернуть кусок и готово.
Код:
function NaAttrib(keyFind: string): boolean;
// keyFind = 'key="DownloadInPlaceDir"'
var
strArr: TArrayOfString;
i: Integer;
begin
Result:= False;
LoadStringsFromFile(strFilename, strArr);
for i:= 0 to GetArrayLength(strArr)-1 do begin
if Pos(keyFind,strArr[i])>0 then
Result:= True;
end;
end;
 

nik1967

Old Men
Проверенный
Хм, заменив в скрипте
GetValue(ExpandConstant('{src}\local.xml'), 'key="DownloadInPlaceDir"', St);
на
GetValue(ExpandConstant('{src}\local.xml'), '<Setting', St);
я получил такой-же результат, но без необходимости дополнительной проверки.
 
Сверху