What is the proper way to test for the existance of an optional node? A snipped of my XML is:
测试可选节点是否存在的正确方法是什么?我的XML片段是:
<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...
天线之子可以是BirdBath或AzEl,但不是两者都…
In Delphi XE I have tried:
在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
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.
我使用XMLSpy创建模式和示例XML,并正确地解析它们。我使用Delphi XE创建绑定,它适用于大多数其他组合。
This must have a simple answer that I have just overlooked - but what? Thanks...... Jim
这一定有一个我刚刚忽略的简单答案——但什么呢?谢谢……吉姆
4 个解决方案
#1
8
You can use XPath, try this sample.
可以使用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;
#2
8
Use .FindNode. It returns nil, if the node doesn't exist.
使用.FindNode。如果节点不存在,则返回nil。
e.g.
如。
xmlNode := MountNode.ChildNodes.FindNode('AzEl');
if Assigned(xmlNode) then
...
#3
1
I have tested it successfully. with this code. It is somewhat more complicated and I need a root element .
我已经测试成功了。这段代码。它有点复杂,我需要一个根元素。
XmlFile
XmlFile
<ThisIsTheDocumentElement>
<Antenna >
<Mount Model="text" Manufacture="text">
<BirdBathMount/>
</Mount>
</Antenna>
<Antenna >
<Mount Model="text" Manufacture="text">
<AzEl/>
</Mount>
</Antenna>
</ThisIsTheDocumentElement>
Delphi2010.pas
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
#4
0
What worked for me was:
对我起作用的是:
if (MountNode.ChildNodes.FindNode('AzEl') <> nil) then
Its not clear to me how the nil
responds to the options setting on TXMLDocumnet like doAttrNull
but it works.
我不清楚nil如何响应TXMLDocumnet上的doAttrNull之类的选项设置,但它确实有效。
#1
8
You can use XPath, try this sample.
可以使用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;
#2
8
Use .FindNode. It returns nil, if the node doesn't exist.
使用.FindNode。如果节点不存在,则返回nil。
e.g.
如。
xmlNode := MountNode.ChildNodes.FindNode('AzEl');
if Assigned(xmlNode) then
...
#3
1
I have tested it successfully. with this code. It is somewhat more complicated and I need a root element .
我已经测试成功了。这段代码。它有点复杂,我需要一个根元素。
XmlFile
XmlFile
<ThisIsTheDocumentElement>
<Antenna >
<Mount Model="text" Manufacture="text">
<BirdBathMount/>
</Mount>
</Antenna>
<Antenna >
<Mount Model="text" Manufacture="text">
<AzEl/>
</Mount>
</Antenna>
</ThisIsTheDocumentElement>
Delphi2010.pas
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
#4
0
What worked for me was:
对我起作用的是:
if (MountNode.ChildNodes.FindNode('AzEl') <> nil) then
Its not clear to me how the nil
responds to the options setting on TXMLDocumnet like doAttrNull
but it works.
我不清楚nil如何响应TXMLDocumnet上的doAttrNull之类的选项设置,但它确实有效。