この回答は、オーストラリアのDelphiユーザーグループのブログ「DanceswithXML」への私のエントリをまとめたものです。さらに詳細が必要な場合は、それを参照してください。
XMLを介したノードへのアクセス
XMLドキュメントにアクセスしてナビゲートするための簡単なメカニズムとしてXPATHを活用しようとすることで、正しい方向に向かっています。実装に少し磨きをかける必要があるというだけです。デモコードを以下に示します。
Q1特定のオブジェクトが存在するかどうかを簡単に確認するにはどうすればよいですか?
XPATH式で「in」演算子を使用し、参照される「DanceswithXML」ユーティリティユニットを使用します。たとえば、提供された入力ドキュメントを使用して、このコードフラグメントは制御ノードが存在するかどうかをテストします。
if 'role/access/control[type="group"]' in XFocus(Root) then
ShowMessage(' Hello! I''m here.')
...ここで、Rootはドキュメントのルートノードです。
Q2タイプグループまたはユーザーのアイテムを簡単に追加するにはどうすればよいですか?
ものを追加するには、流暢なAPIを備えたXMLライブラリが最適ですが、次の方法で半流暢にすることができます。
子要素を追加する
子要素を追加するには、次のようなコードを使用します...
ParentNode.AddChild('child-name')
上記の式はIXMLNodeを返す関数であるため、これはやや流暢です。
属性を追加する
新しい属性を追加したり、既存の属性を変更したりするには、次のようなコードを使用します...
ElementNode.Attributes['myattrib'] := 'attrib-value'
この機能のネイティブべき等バージョンはありませんが、独自のバージョンを作成するのは簡単です。
例1
この例は、質問で与えられたOPのTest()プロシージャの機能を大まかに複製します。
// uses uXMLUtils from referenced demo.
procedure Test;
begin
Doc := LoadDocument_MSXML_FromStream( TestXMLStream);
Root := Doc.Node;
// To test if control node exists:
if 'role/access/control' in XFocus(Root) then
ShowMessage('The control node exists!');
// To access each control node:
for ControlNode in 'role/access/control' then
DoSomethingForEachControlNode( ControlNode);
// To access on the first control node:
for ControlNode in '(role/access/control)[1]' then
DoSomethingForFirstControlNode( ControlNode);
// To access on the first control node which has BOTH group type and Admin object:
for ControlNode in '(role/access/control[type="group"][object="COMPUTER\Administrators"])[1]' do
DoSomething( ControlNode);
// To do something for EACH control node which is EITHER group type or Admin object:
for ControlNode in 'role/access/control[type="group" or object="COMPUTER\Administrators"]' do
DoSomething( ControlNode);
終わり;
例2
コンピューター管理者グループを追加したいとしますが、まだ存在していない場合に限ります。追加する場合、新しいノードは新しいアクセスノードの下に配置されます。XPATHを活用すれば、わずかな量のコードでこれを実現できます。これは、以下のコードフラグメントに示されています。
if not 'role/access/control[type[.="group"][object[.="COMPUTER\Administrators"]]' in XFocus(Root) then
begin
ControlNode := Root.ChildNodes.FindNode('role')
.AddChild(['access')
.AddChild('control');
ControlNode.AddChild('type' ).Text := 'group';
ControlNode.AddChild('object').Text := 'COMPUTER\Administrators'
end;