2012-06-15 40 views
6

什麼是測試可選節點存在的正確方法?我的XML的文檔片斷是:如何測試某個XML節點是否存在?

<Antenna > 
    <Mount Model="text" Manufacture="text"> 
    <BirdBathMount/> 
    </Mount> 
</Antenna> 

但它也可能是:

<Antenna > 
    <Mount Model="text" Manufacture="text"> 
    <AzEl/> 
    </Mount> 
</Antenna> 

天線的孩子既可以是水盆或亞悉但不能同時...

在Delphi XE我曾嘗試過:

if (MountNode.ChildNodes.Nodes['AzEl'] <> unassigned then //Does not work 
if (MountNode.ChildNodes['BirdBathMount'].NodeValue <> null) then // Does not work 
if (MountNode.BirdBathMount.NodeValue <> null) then // Does not work 

我使用XMLSpy創建架構和示例XML並正確解析它們。我使用Delphi XE來創建綁定,並且它適用於大多數其他組合。

必須有一個簡單的答案,我剛忽略 - 但是什麼? 謝謝...... Jim

+1

您是否嘗試過單元「Variants」中的「VarIsNull()」? – paulsm4

回答

8

您可以使用XPath,試試這個示例。

uses 
    MSXML; 


Var 
    XMLDOMDocument : IXMLDOMDocument; 
    XMLDOMNode  : IXMLDOMNode; 
begin 
    XMLDOMDocument:=CoDOMDocument.Create; 
    XMLDOMDocument.loadXML(XmlStr); 
    XMLDOMNode := XMLDOMDocument.selectSingleNode('//Antenna/Mount/BirdBathMount'); 
    if XMLDOMNode<>nil then 
    Writeln('BirdBathMount node Exist') 
    else 
    begin 
    XMLDOMNode := XMLDOMDocument.selectSingleNode('//Antenna/Mount/AzEl'); 
    if XMLDOMNode<>nil then 
     Writeln('AzEl node Exist'); 
    end; 
end; 
+1

XPath的+1。由於該文件已經存在於任何真實世界的測試中,上述代碼示例可能確實是'selectSingleNode'調用。 –

+1

請注意,這是Microsoft特有的。如果「DOMVendor」設置爲MSXML(Windows上的默認設置),則可以將XPath與「TXMLDocument/IXMLDocument」一起使用。 –

+0

你是對的。在我忽略的問題中「天線的孩子可以是BirdBath或AzEl,但不能同時......」。如果我刪除我的評論,對你來說可以嗎? –

1

我已經測試成功。與此代碼。它有點複雜,我需要一個根元素。

XMLFILE

<ThisIsTheDocumentElement> 
<Antenna > 
    <Mount Model="text" Manufacture="text"> 
    <BirdBathMount/> 
    </Mount> 
</Antenna> 
<Antenna > 
    <Mount Model="text" Manufacture="text"> 
    <AzEl/> 
    </Mount> 
</Antenna> 
</ThisIsTheDocumentElement> 

Delphi2010.pas

procedure TForm1.RetrieveDocument; 
var 
    LDocument: IXMLDocument; 
    LNodeElement, LNode,BNode,CNode : IXMLNode; 
    I: Integer; 
begin 
    LDocument := TXMLDocument.Create(nil); 
    LDocument.LoadFromFile(XmlFile); 
    LNodeElement := LDocument.ChildNodes.FindNode('ThisIsTheDocumentElement'); 
    if (LNodeElement <> nil) then 
    begin 
    for I := 0 to LNodeElement.ChildNodes.Count - 1 do 
    begin 
     LNode := LNodeElement.ChildNodes.Get(I); 
     if (LNode <> Nil) AND (LNode.NodeName='Antenna') then begin 
      Memo1.lines.Add('Node name: ' + LNode.NodeName); 
      BNode:=LNode.ChildNodes.FindNode('Mount'); 
     if (BNode <> Nil) then CNode:=BNode.ChildNodes.FindNode('AzEl'); 
      if (CNode <> Nil) then Memo1.lines.Add('found: '+CNode.NodeName) else continue; 
     end; 
    end; 
    end; 
end; 

OUTPUT:

Node name: Antenna 
Node name: Antenna 
found: AzEl 
+0

對我有效的是:'code'if(MountNode.ChildNodes.FindNode('AzEl')<>無)然後 '代碼' –

+0

在我的例子。 BNode == MountNode –

+0

@ moskito-x XPath語句'// Antenna/Mount/BirdBathMount'和'// Antenna/Mount/AzEl'適用於OP發佈的xml,也許您正在嘗試使用另一個xml。 – RRUZ

8

使用.FindNode。如果節點不存在,它將返回nil。

例如

xmlNode := MountNode.ChildNodes.FindNode('AzEl'); 
if Assigned(xmlNode) then 
... 
+1

這是最終爲我工作的那個。 {code} if(MountNode.ChildNodes.FindNode('AzEl')<> nil)then {code} –

+0

在我的例子中。 BNode == MountNode –

0

什麼工作對我來說是:

if (MountNode.ChildNodes.FindNode('AzEl') <> nil) then 

它不是很清楚,我的nil如何響應的選項設置上TXMLDocumnet像doAttrNull,但它的工作原理。

相關問題