How do I test whether a certain XML node exists?
12,410
Solution 1
You can use XPath, try this sample.
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;
Solution 2
Use .FindNode. It returns nil, if the node doesn't exist.
e.g.
xmlNode := MountNode.ChildNodes.FindNode('AzEl');
if Assigned(xmlNode) then
...
Solution 3
I have tested it successfully. with this code. It is somewhat more complicated and I need a root element .
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
Related videos on Youtube
Author by
Seti Net
Building the only operational SETI Station in the US
Updated on September 16, 2022Comments
-
Seti Net over 1 year
What is the proper way to test for the existance of an optional node? A snipped of my XML is:
<Antenna > <Mount Model="text" Manufacture="text"> <BirdBathMount/> </Mount> </Antenna>
But it could also be:
<Antenna > <Mount Model="text" Manufacture="text"> <AzEl/> </Mount> </Antenna>
The child of Antenna could either be BirdBath or AzEl but not both...
In Delphi XE I have tried:
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
I use XMLSpy to create the schema and the example XML and they parse correctly. I use Delphi XE to create the bindings and it works on most other combinations fine.
This must have a simple answer that I have just overlooked - but what? Thanks...... Jim
-
paulsm4 almost 12 yearsHave you tried "VarIsNull()" from unit "Variants"?
-
-
Warren P almost 12 years+1 for XPath. Since the document already would exist in any real world test, the above code sample could really be the
selectSingleNode
call. -
Remy Lebeau almost 12 yearsNote that this is Microsoft-specific. You can use XPath with
TXMLDocument/IXMLDocument
if theDOMVendor
is set to MSXML (the default on Windows). -
Seti Net almost 12 yearsThis is the one that finally worked for me. {code} if (MountNode.ChildNodes.FindNode('AzEl') <> nil) then {code}
-
Seti Net almost 12 yearsWhat worked for me was:'code'if (MountNode.ChildNodes.FindNode('AzEl') <> nil) then 'code'
-
moskito-x almost 12 yearsIn My example. BNode == MountNode
-
moskito-x almost 12 yearsIn My example. BNode == MountNode
-
RRUZ almost 12 years@moskito-x the XPath sentences
//Antenna/Mount/BirdBathMount
and//Antenna/Mount/AzEl
works with the xml posted by the OP, maybe you are trying with another xml. -
moskito-x almost 12 years@RRUZ I've tried it with a TMemo. The file "XMLFile.xml" (from my answer) loaded with load file and the String "xmlstr" xmlstr:= Memo1.Text; passed. With and without "<ThisIsTheDocumentElement> "
-
RRUZ almost 12 years@moskito-x, try with the XML posted by the OP, if yuu want try with you xml version try using
//ThisIsTheDocumentElement/Antenna/Mount/BirdBathMount
instead -
moskito-x almost 12 yearsYOU ARE RIGHT.!!! In The Question I overlooked "The child of Antenna could either be BirdBath or AzEl but not both..." . Is It OK for you,if I delete my comments ??