让我的XML看起来很棒!德尔福:)

时间:2010-11-19 12:04:41

标签: xml delphi

嘿,从帖子请求我得到一个xml文件的响应。 例如

'<?xml version="1.0" encoding="UTF-8" ?>'#$D#$A'<PosXML version="6.0.2">'#$D#$A#9'<ShowInfoResponse>'#$D#$A#9#9'<ReturnCode>0</ReturnCode>'#$D#$A#9'</ShowInfoResponse>'#$D#$A'</PosXML>'

问题是我如何纠正,因为我需要将它发送到LoadXMLData('Here');

以下是代码:

procedure TForm1.Button3Click(Sender: TObject);
var
xmldocument1:ixmldocument;
responseNode:ixmlnode;
test:string;
begin
xmldocument1 := loadxmldata('<?xml version="1.0" encoding="UTF-8" ?>'#$D#$A'<PsXML>'#$D#$A#9'<ShowInfo>'#$D#$A#9#9'<Code>1234</Code>'#$D#$A#9'</ShowInfo>'#$D#$A'</PsXML>');
responsenode := xmldocument1.DocumentElement.childnodes.Findnode('Code');
test := responsenode.ChildNodes[0].Text;

问题是test(string)总是会产生异常,因为responsenode是零。 提前谢谢!

6 个答案:

答案 0 :(得分:4)

错误地认为您的XML存在问题。

DocumentElement属性为您提供对PsXMLPosXML节点的引用。读取该属性的ChildNodes属性会为您提供该节点的子节点列表。但是,该列表只包含一个元素,ShowInfo节点或ShowInfoResponse。在该列表上调用FindNode只能为您提供其中一个值。 它不会搜索列表中节点的子节点。由于文档元素没有子Code元素,FindNode正确返回nil

我怀疑你对调试器感到困惑。您的程序从网络中获取了某些内容,并将其存储在字符串中。您正在使用调试器来查看该字符串中的内容,并且调试器向您显示带有一堆数字符号和美元符号的内容,您确定不应该在那里。您的代码没有选择正确的节点,因此您得出结论,混乱的XML字符串必须是原因。

但XML是正确的。而且它甚至已经打印出来了!它有换行符和制表符来缩进。但调试器想要显示一个明确的字符串。如果它显示了一个实际的多行字符串和缩进的东西,那么你作为程序员就不会知道字符串中的真正内容。相反,调试器会显示无法显示的字符的数字字符代码。回车符和换行符分别具有数值13和10,以十六进制表示D和A.调试器使用Delphi自己的字符串文字格式显示值;数字字符文字引入了#符号,后跟字符的数字代码。 $表示该数字为十六进制。

答案 1 :(得分:3)

要“漂亮打印”XML代码,您可以使用Delphi函数FormatXMLData。但是,LoadXMLData并没有为人类可读性提供奖励积分,因此原始字符串就可以了。

答案 2 :(得分:1)

此字符串适用于LoadXMLData而无需更改。白色空间和回车等事情被忽略了。

答案 3 :(得分:0)

你正在寻找错误的节点,这就是它返回nil的原因。你必须寻找'ReturnCode'而不是'Code'。

答案 4 :(得分:0)

我认为你的问题是Code是ShowInfoResponse的Child节点。那怎么样:

responsenode := xmldocument1.DocumentElement.childnodes[0];
test := responsenode.ChildNodes['Code'].Text;

答案 5 :(得分:0)

IXMLNodeList.FindNode方法仅在列表中包含的节点上查找搜索NodeName,而不在子节点中查找。

如果您想要查看整个树,请使用此功能:

function RecursiveFindNode(ANode: IXMLNode; const SearchNodeName: string): IXMLNode;
var
  I: Integer;
begin
  if CompareText(ANode.NodeName, SearchNodeName) = 0 then
    Result := ANode
  else if not Assigned(ANode.ChildNodes) then
    Result := nil
  else begin
    for I := 0 to ANode.ChildNodes.Count - 1 do
    begin
      Result := RecursiveFindNode(ANode.ChildNodes[I], SearchNodeName);
      if Assigned(Result) then
        Exit;
    end;
  end;
end;

然后,做这样的事情:

var
  I: Integer;
  ANode: IXMLNode;
begin
  xmldocument1 := loadxmldata('<?xml version="1.0" encoding="UTF-8" ?>'#$D#$A'<PsXML>'#$D#$A#9'<ShowInfo>'#$D#$A#9#9'<Code>1234</Code>'#$D#$A#9'</ShowInfo>'#$D#$A'</PsXML>');
  ANode := RecursiveFindNode(xmlDocument1.DocumentElement, 'Code');  //or ReturnCode if you use the first version of the XML
  if Assigned(ANode) then
    ShowMessage('Eureka!');
end;

警告以这种方式查找节点的效率非常低。如果您可以预见文档结构,最好使用该知识来导航文档并仅在需要时使用搜索。