这个答案总结了我在澳大利亚德尔福用户组博客“Dances with XML”上的条目。如果您需要更多详细信息,请参阅它。
通过 XML 访问节点
通过尝试利用 XPATH 作为访问和浏览 XML 文档的简单机制,您正朝着正确的方向前进。只是您的实现需要一些改进。演示代码如下所示。
Q1 如何轻松检查给定对象是否存在?
使用带有 XPATH 表达式的 'in' 运算符和引用的“Dances with XML”实用程序单元。例如,使用您提供的输入文档,此代码片段测试控制节点是否存在
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;