[英]Search data in XML using IXMLDocument
鑒於下面的XML示例;
<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)創建dom后添加以下行:
Doc.setProperty('SelectionLanguage', 'XPath');
2)更好的是,您可以更明確地了解要創建的解析器版本,並使用以下內容替換構造線:
Doc := CoDOMDocument60.Create;
如果查詢沒有找到任何內容,則Node將為空。
if not Assigned(Node) then...
MSXML3解析器的默認查詢語言是XSLPatterns。 您需要將其顯式設置為XPath。 已經有一段時間了,因為我必須處理它,但我認為CreateOleObject行必須創建我的默認MSXML解析器。
更新:你的問題的后半部分的解決方案是從優雅的TLama無恥地(經許可)偷走的。 :)
忽略目標文檔格式和錯誤處理,例如這樣:
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共舞”中的條目。 如果您需要更多細節,請參閱它。
通過嘗試利用XPATH作為訪問和瀏覽XML文檔的簡單機制,您將朝着正確的方向前進。 只是你的實現需要一些拋光。 示范代碼如下所示。
使用帶有XPATH表達式的“in”運算符和引用的“Dances with XML”實用程序單元。 例如,使用您提供的輸入文檔,此代碼片段將測試控制節點是否存在
if 'role/access/control[type="group"]' in XFocus(Root) then
ShowMessage(' Hello! I''m here.')
...其中Root是文檔根節點。
對於添加內容,使用具有流暢API的XML庫是最好的,但您可以使用以下方法實現半流暢性:
要添加子元素,請使用以下代碼...
ParentNode.AddChild('child-name')
這是半流利的,因為上面的表達式是一個返回IXMLNode的函數。
要添加新屬性,或更改現有屬性,請使用以下代碼...
ElementNode.Attributes['myattrib'] := 'attrib-value'
此功能沒有本機冪等版本,但滾動自己的功能將是微不足道的。
這個例子粗略地復制了問題中給出的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);
結束;
假設我們想要添加一個計算機管理員組,但前提是它還不存在。 如果添加,新節點將進入新的訪問節點。 如果我們利用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.