Skip to content

Instantly share code, notes, and snippets.

@rwilkes
Forked from seraphy/XMLParseExample.iss
Created April 26, 2018 02:00
Show Gist options
  • Save rwilkes/bc9a428523a5611edda03768fde7f518 to your computer and use it in GitHub Desktop.
Save rwilkes/bc9a428523a5611edda03768fde7f518 to your computer and use it in GitHub Desktop.
Inno SetupでMSXMLを使ったXMLの解析の実装例(Ansi/Unicode版どちらでもOK)
[Setup]
AppId=XMLParseExample
AppName=XMLParseExample
AppVersion=1.0.0
VersionInfoVersion=1.0.0
VersionInfoDescription={#SetupSetting("AppName")} Installer
OutputBaseFilename={#SetupSetting("AppName")}_{#SetupSetting("AppVersion")}
DefaultDirName={sd}\{#SetupSetting("AppName")}
DefaultGroupName=InnoSetupScriptExample
OutputDir=.
SetupLogging=yes
[Code]
const
PROGID_DOMDocument60 = 'Msxml2.DOMDocument.6.0';
type
{ KeyValueペアの構造体 }
TKeyValue = record
Key: String;
Value: String;
end;
{ Properties XMLを読み込んでKeyValueペアの配列を返す. }
{ 読み込みに失敗した場合は例外を上げる }
function ReadPropertiesXML(const XML: String): array of TKeyValue;
var
XMLDoc: Variant;
Nodes: Variant;
Node: Variant;
Attr: Variant;
Key: String;
Val: String;
Idx: Integer;
KeyValue: TKeyValue;
begin
// CreateOleObject系はInno Setup Ansi版/Unicode版のどちらでもOK
XMLDoc := CreateOleObject(PROGID_DOMDocument60);
XMLDoc.setProperty('SelectionLanguage', 'XPath');
XMLDoc.Async := False;
if not XMLDoc.LoadXML(XML) then begin
if (XMLDoc.parseError.errorCode <> 0) then begin
// XML形式として不正な場合
RaiseException(XMLDoc.parseError.reason);
end else begin
RaiseException('Failed to parse xml. (unknown reason)');
end;
exit;
end;
Nodes := XMLDoc.selectNodes('//properties/property');
For Idx := 0 to Nodes.Length - 1 do
begin
Node := Nodes.Item(Idx);
Attr := Node.Attributes.GetNamedItem('key');
if IDispatch(Attr) <> Nil then begin // VarIsNullではダメ
KeyValue.Key := Attr.Text;
KeyValue.Value := Node.Text;
//Log('key=' + KeyValue.Key + ',value=' + KeyValue.Value);
SetArrayLength(Result, GetArrayLength(Result) + 1);
Result[GetArrayLength(Result) - 1] := KeyValue;
end;
end;
end;
function TryGetValue(
const KeyValueList: array of TKeyValue;
const KeyName: String;
var Value: String
): Boolean;
var
Idx: Integer;
begin
for Idx := 0 to GetArrayLength(KeyValueList) - 1 do
begin
if KeyValueList[Idx].Key = KeyName then begin
// マッチした場合(最初にマッチしたもので打ち切る)
Value := KeyValueList[Idx].Value;
Result := True;
Exit;
end;
end;
// 発見できず
Result := False;
end;
{ 開始ハンドラ }
function InitializeSetup(): Boolean;
var
XML: String;
props: array of TKeyValue;
Idx: Integer;
Value: String;
begin
// Properties XML
XML := '<?xml version="1.0"?><properties>' +
'<property key="key1">val1</property>' +
'<property key="key2">val2</property>' +
'<property key="key3"/>' + // 単一タグケース
'<property keyX="xxx"/>' + // Attr不正ケース
'</properties>';
props := ReadPropertiesXML(XML);
// 読み取り結果一覧
for Idx := 0 to GetArrayLength(props) - 1 do
begin
Log('key=' + props[Idx].Key + ',value=' + props[Idx].Value);
end;
// キーを指定して表示
if TryGetValue(props, 'key1', value) then Log('>key1=' + value);
if TryGetValue(props, 'key2', value) then Log('>key2=' + value);
if TryGetValue(props, 'key3', value) then Log('>key3=' + value);
if TryGetValue(props, 'key4', value) then Log('>key4=' + value);
Result := False; // 継続せずに、ここで終了する
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment