繁体   English   中英

使用IXMLDocument以XML格式搜索数据

[英]Search data in XML using IXMLDocument

鉴于下面的XML示例;

  1. 如何轻松检查给定对象是否存在?
  2. 如何轻松添加类型组或用户的项目? (添加一整块)

<role>
    <access>
        <control>
            <type>group</type>
            <object>COMPUTER\Administrators</object>
        </control>
        <control>
            <type>user</type>
            <object>COMPUTER\Admin</object>
        </control>
    </access>
</role>

码:

var
  Doc: IXMLDOMDocument2;
  Node: IXMLDOMNode;
procedure Test;
begin
  Doc := CreateOleObject('Microsoft.XMLDOM') as IXMLDomDocument2;
  Doc.load('test.xml');

  // This Works
  Node := Doc.selectSingleNode('//role/access/control');

  // But this does not work:
  Node := Doc.selectSingleNode('//role/access/control[type = ''group'']');

  // EDIT: This does work, but how to combine with object=COMPUTER\Admin?
  Node := Doc.selectSingleNode('//role/access/control[type="group"]');

  // EDIT: This does not work either
  Node := Doc.selectSingleNode('//role/access/control[type="group" and object="COMPUTER\Administrators"]');
end;

1.如何修复XPath表达式?

以下任何一个都将修复查询:

1)创建dom后添加以下行:

  Doc.setProperty('SelectionLanguage', 'XPath');

2)更好的是,您可以更明确地了解要创建的解析器版本,并使用以下内容替换构造线:

Doc := CoDOMDocument60.Create; 

如果查询没有找到任何内容,则Node将为空。

if not Assigned(Node) then...

MSXML3解析器的默认查询语言是XSLPatterns。 您需要将其显式设置为XPath。 已经有一段时间了,因为我必须处理它,但我认为CreateOleObject行必须创建我的默认MSXML解析器。

更新:你的问题的后半部分的解决方案是从优雅的TLama无耻地(经许可)偷走的。 :)

2.如何添加“控制”节点?

忽略目标文档格式和错误处理,例如这样:

procedure TForm1.Button2Click(Sender: TObject);
var
  XMLRoot: IXMLDOMNode;
  XMLChild: IXMLDOMNode;
  XMLDocument: IXMLDOMDocument2;
begin
  XMLDocument := CreateOleObject('Microsoft.XMLDOM') as IXMLDomDocument2;
  XMLDocument.load('XMLFile.xml');
  XMLRoot := XMLDocument.selectSingleNode('//role/access');
  if Assigned(XMLRoot) then
  begin
    XMLRoot := XMLRoot.appendChild(XMLDocument.createElement('control'));
    XMLChild := XMLRoot.appendChild(XMLDocument.createElement('type'));
    XMLChild.text := 'user';
    XMLChild := XMLRoot.appendChild(XMLDocument.createElement('object'));
    XMLChild.text := 'COMPUTER\TLama';
    XMLDocument.save('XMLFile.xml');
  end;
end;

这个答案总结了我在澳大利亚Delphi用户组博客“与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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM