IXMLDocument 的Node属性和DocumentElement属性区别

今天写一个Xml配置的读写类,遇到了几个问题,记录如下。

1)读一个并不存在的节点竟然不出问题?

用了一个很简单的 xml 文件,如下 

<!--  test.xml  -->
<? xml version="1.0" encoding="GB2312" ?>
< value >
   
< v >  abc def ghi  </ v >
</ value >

读写代码如下:

//  竟然没有delphi的代码模版?kao

procedure TForm1.btnReadClick(Sender: TObject);
var
  N: IXMLNode;
  St: TStringList;
  I: Integer;    
begin
  St :
=  TStringList.Create;
  
try
    St.Text :
=  edtNodeName.Text;
    St.Text :
=  StringReplace(St.Text,  ' / ' , # 13 # 10 , [rfReplaceAll]);   //  输入的Node序列格式为"ParentNode/SubNode",
    N : =  xmldoc1.DocumentElement;
    
for  I : =   0  to St.Count  -   1   do
    begin
      N :
=  N.ChildNodes.Nodes[St[I]];
      
if  N  =  nil then
        MessageDlg(Format(
' 无此节点 "%s" ' , [St[I]]), mtError, [mbOK] ,  0 );
    end;
    
if  N  <>  nil then
      
if  not N.IsTextElement then
      begin
        MessageDlg(
' not text node ' , mtInformation, [mbOK],  0 );
        edtResult.Text :
=  Format( ' %s is %s ' , [N.NodeName, NodeTypeToStr(N.NodeType)]);
      end
      
else
        edtResult.Text :
=  N.Text;
  
finally
    St.Free;
  end;
end;

该代码从名为 btnNodeName  的编辑框中读取Node的名字,支持多层级,如要读取上面的test.xml文件的v节点的值,只要输入 “value/v” (写这段代码时是这样想的,但是这样想是错误的,后面有说明).

但是,测试的时候,发现总是报 v 不是 TextElement,百思不得其解,后来无意中发现原来执行时打开的是另外一个xml文件,但是该xml文件的结构完全不一样,压根就没有 value 和 v 节点,怎么还能够读取到这两个节点呢?

仔细看了一下帮助,在对 IXMLNodeList.Nodes属性的解释中,发现了这段说明:

If IndexOrName does not identify a node in the list, and if the document that contains this node list's parent includes doNodeAutoCreate in its Options property, then the node list tries to create a new node with the name specified by IndexOrName. If the node list can't create the new node, it raises an exception.

原来,如果 Nodes 属性的参数 IndexOrName(为结点名时) 所指定的节点不存在,并且 其所属的 IXmlDocument 的 Options 属性包含了doNodeAutoCreate值,则会自动创建一个新的节点,命名为 IndexOrName 的值,所以才会出现读取不存在的节点也不会出错的现象,而且因为该节点加入后,没有设置值,所以类型是ntElement,而不是ntText,所以会报不是 TextElement。我们只要在创建IXmlDocument对象后加入下面的代码就可避免这种情况:

xmlDoc : =  TXmlDocument.Create(nil);
xmlDoc.Options :
=  xmlDoc.Options  -  [doNodeAutoCreate];

2)value 节点不存在?

修正了上面的问题之后测试,edtNodeName 输入为“value/v”,报错,提示“value”节点不存在,奇怪,怎么会不存在,这回打开的确实是test.xml文件啊。查看代码,发现 TXMLDocument 读取 DocmentElement 属性是这样实现的:

function TXMLDocument.GetDocumentElement: IXMLNode;
begin
  CheckActive;
  Result :
=  nil;
  
if  Node.HasChildNodes then
  begin
    Result :
=  Node.ChildNodes.Last;
    
while  Assigned(Result) and (Result.NodeType  <>  ntElement)  do
      Result :
=  Result.PreviousSibling;
  end;
end;

这个 Node 是个什么东西?继续查看有关 Node 的代码,并且翻看帮助,帮助是这样说的:

Read Node to access the document node for the XML document. The document node represents information about the entire document. It may have several child nodes, which represent comments, processing instructions, and which include the DocumentElement node that acts as the root of the data hierarchy.

原来 Node 才是 xml 文档的真正根节点,而 DocumentElement 只是我们的xml文件的内容的根节点,是 Node 的子节点,对于上面的 test.xml 来说, DocmentElement 就是表示 value 节点,而在上面的代码中,我们实际上读取的是“value/value”节点,难怪会不存在,把上面的

N := xmldoc1.DocumentElement;

改为

N := xmldoc1.Node;

就 OK 了。

你可能感兴趣的:(IXMLDocument 的Node属性和DocumentElement属性区别)