2012-06-15 28 views
6

¿Cuál es la forma correcta de probar la existencia de un nodo opcional? Un cortó de mi XML es:¿Cómo compruebo si existe un determinado nodo XML?

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

Pero también podría ser:

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

El niño de la antena podría ser o bien Bañera de Pájaros o AZEL pero no tanto ...

En Delphi XE Lo he intentado:

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 

Uso XMLSpy para crear el esquema y el ejemplo XML y se analizan correctamente. Uso Delphi XE para crear los enlaces y funciona bien en la mayoría de las otras combinaciones.

tiene tiene una respuesta simple que acabo de pasar por alto, pero ¿qué? Gracias ...... Jim

+1

¿Has probado "VarIsNull()" de la unidad "Variantes"? – paulsm4

Respuesta

8

Puede usar XPath, pruebe esta muestra.

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

+1 para XPath. Como el documento ya existiría en cualquier prueba del mundo real, la muestra de código anterior podría ser realmente la llamada 'selectSingleNode'. –

+1

Tenga en cuenta que esto es específico de Microsoft. Puede usar XPath con 'TXMLDocument/IXMLDocument' si el' DOMVendor' está configurado a MSXML (el predeterminado en Windows). –

+0

¡ERES CORRECTO! En The Question pasé por alto que "el hijo de Antenna podría ser BirdBath o AzEl pero no ambos ...". ¿Está bien para ti, si borro mis comentarios? –

1

Lo he probado con éxito. con este código Es algo más complicado y necesito un elemento raíz.

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; 

SALIDA:

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

Lo que funcionó para mí fue: 'code'if (MountNode.ChildNodes.FindNode (' AzEl ') <> nil) luego ' código ' –

+0

En mi ejemplo. BNode == MountNode –

+0

@ moskito-x las oraciones XPath '// Antenna/Mount/BirdBathMount' y' // Antenna/Mount/AzEl' funciona con el xml publicado por el OP, quizás esté intentando con otro xml. – RRUZ

8

Uso .FindNode. Devuelve nil, si el nodo no existe.

p. Ej.

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

Este es el que finalmente funcionó para mí. {code} if (MountNode.ChildNodes.FindNode ('AzEl') <> nil) luego {code} –

+0

En mi ejemplo. BNode == MountNode –

0

lo que funcionó para mí fue:

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

No es claro cómo la nil responde a las opciones de configuración en TXMLDocumnet como doAttrNull pero funciona.

Cuestiones relacionadas