2012-06-15 4 views
6

Каков правильный способ проверить наличие необязательного узла? Отрезала моего XML является:Как проверить, существует ли определенный узел XML?

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

Но это также может быть:

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

Ребенок Антенна может быть либо Birdbath или Азеля, но не оба ...

В 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

Вы пробовали "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

+1 для XPath. Поскольку этот документ уже существует в любом реальном тесте, приведенный выше пример кода действительно может быть вызовом 'selectSingleNode'. –

+1

Обратите внимание, что это зависит от Microsoft. Вы можете использовать XPath с 'TXMLDocument/IXMLDocument', если' DOMVendor' установлен в MSXML (по умолчанию в Windows). –

+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; 

ВЫВОД:

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

Что для меня работало: 'code'if (MountNode.ChildNodes.FindNode (' AzEl ') <> nil), затем ' code ' –

+0

В моем примере. BNode == MountNode –

+0

@ moskito-x предложения XPath '// Antenna/Mount/BirdBathMount' и' // Antenna/Mount/AzEl' работает с xml, отправленным OP, возможно, вы пытаетесь использовать другой xml. – RRUZ

8

Использование .FindNode. Он возвращает nil, если узел не существует.

например.

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

Это тот, который, наконец, работал для меня. {code} if (MountNode.ChildNodes.FindNode ('AzEl') <> nil), затем {code} –

+0

В моем примере. BNode == MountNode –

0

То, что сработало для меня было:

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

Его мне не ясно, каким образом nil реагирует на параметры настройки на TXMLDocumnet как doAttrNull, но это работает.

Смежные вопросы