0

我的代码是:

  XmlDoc := NewXMLDocument;
  with XmlDoc do
    Options := Options + [doNodeAutoIndent];
[...]
  N := Parent.ChildNodes.FindNode('KONTRAHENT');
  while N <> nil do
  begin
    if N.ChildNodes['ID_KONTRAHENTA'].NodeValue = KontrNr then
      DoSomething;
    N := N.NextSibling;
  end;

和这样的XML:

<KARTOTEKA_KONTRAHENTOW>
   <KONTRAHENT>
      <ID_KONTRAHENTA>925</ID_KONTRAHENTA>
   </KONTRAHENT>
   <KONTRAHENT>
      <ID_KONTRAHENTA>1208</ID_KONTRAHENTA>
   </KONTRAHENT>
</KARTOTEKA_KONTRAHENTOW>

在 Watch Parent.XML 中查看的数据看起来:

'<KARTOTEKA_KONTRAHENTOW>'#$D#$A#9#9'<KONTRAHENT>'#$D#$A#9#9#9'<ID_KONTRAHENTA>925</ID_KONTRAHENTA>'#$D#$A#9#9'</KONTRAHENT>'#$D#$A#9#9'<KONTRAHENT>'#$D#$A#9#9#9'<ID_KONTRAHENTA>1208</ID_KONTRAHENTA>'#$D#$A#9#9'</KONTRAHENT>'#$D#$A#9'</KARTOTEKA_KONTRAHENTOW>'

当我在循环中读取节点时,当 Options: [doNodeAutoIndent] 设置时,我有一些像这样的节点:N = '#$D#$A#9#9' 并且节点数 = 7(而不是 2,在这个例子中)

没有 doNodeAutoIndent,一切正常,节点数 = 2,但我的 XML 文件在一行中:(

问题是:启用 doNodeAutoIndent 时如何绕过空的 NextSibling?

4

1 回答 1

1

你所描述的完全正常。元素之间的空白被视为层次结构中的附加文本节点,例如,对于您的示例 XML,其 DOM 树如下所示:

KARTOTEKA_KONTRAHENTOW
|_ '#$D#$A#9#9'
|_ KONTRAHENT
|  |_ '#$D#$A#9#9#9'
|  |_ ID_KONTRAHENTA
|  |  |_ '925'
|  |_ '#$D#$A#9#9'
|_ '#$D#$A#9#9'
|_ KONTRAHENT
|  |_ '#$D#$A#9#9#9'
|  |_ ID_KONTRAHENTA
|  |  |_ '1208'
|  |_ '#$D#$A#9#9'
|_ '#$D#$A#9'

这就是为什么节点数比您预期的要高。

您需要在循环元素时考虑这些额外的文本节点,例如:

N := Parent.ChildNodes.First;
while N <> nil do
begin
  if (N.NodeType = ntElement) and (N.NodeName = 'KONTRAHENT') then
  begin
    if N.ChildNodes['ID_KONTRAHENTA'].NodeValue = KontrNr then
    begin
      // Do something with N ...
    end;
  end;
  N := N.NextSibling;
end;

或者,使用 XPath 查询来只关注您真正想要的节点,例如:

uses
  ..., XmlIntf, XmlDom;

var
  ...
  XPath: IDOMNodeSelect;
  Nodes: IDOMNodeList;
  N: IDOMNode;
  I: Integer;

...

if Supports(Parent.DOMNode, IDOMNodeSelect, XPath) then
begin
  Nodes := XPath.selectNodes('KONTRAHENT[ID_KONTRAHENTA='+IntToStr(KontrNr)+']');
  for I := 0 to Nodes.length-1 do
  begin
    N := Nodes[i];
    // do something with N ...
  end;
end else
begin
  // code shown above ...
end;
于 2020-12-18T17:58:38.457 回答