Мой код:
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>'
И когда я читаю узлы в цикле, когда установлены параметры: [doNodeAutoIndent] тогда у меня есть такие узлы: N = '#$D#$A#9#9' и количество узлов = 7 (вместо 2 в этом примере)
Без doNodeAutoIndent все в порядке и Count of Nodes = 2, но мой XML-файл находится в одной строке :(
Вопрос в том: Как обойти пустой NextSibling, когда включен doNodeAutoIndent?
Спасибо. Я думал об этом и не заметил, что не задал вопрос. Вопрос: "Как обойти пустой NextSibling при включенном doNodeAutoIndent?"
То, что вы описываете, совершенно нормально. Пробелы между элементами рассматриваются как дополнительные текстовые узлы в иерархии, например, для вашего примера 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;
Спасибо, @remy-lebeau
Хорошо, но где вопрос?