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
Share:
12,410

Related videos on Youtube

Seti Net
Author by

Seti Net

Building the only operational SETI Station in the US

Updated on September 16, 2022

Comments

  • Seti Net
    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
      paulsm4 almost 12 years
      Have you tried "VarIsNull()" from unit "Variants"?
  • Warren  P
    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
    Remy Lebeau almost 12 years
    Note that this is Microsoft-specific. You can use XPath with TXMLDocument/IXMLDocument if the DOMVendor is set to MSXML (the default on Windows).
  • Seti Net
    Seti Net almost 12 years
    This is the one that finally worked for me. {code} if (MountNode.ChildNodes.FindNode('AzEl') <> nil) then {code}
  • Seti Net
    Seti Net almost 12 years
    What worked for me was:'code'if (MountNode.ChildNodes.FindNode('AzEl') <> nil) then 'code'
  • moskito-x
    moskito-x almost 12 years
    In My example. BNode == MountNode
  • moskito-x
    moskito-x almost 12 years
    In My example. BNode == MountNode
  • RRUZ
    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
    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
    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
    moskito-x almost 12 years
    YOU 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 ??