Well, what else do you want to get with such a data and such a request ?
With the request "//Gordijn[1]/Kamerkant[1]/node()" you literally ask for "all the nodes withing Kamerkant[1]"
But your Kamerkant
is an empty node - it contains ZERO nodes inside it.
So the result of your request - to extract nodes from the container lacking nodes inside - can only be NULL or empty set having nothing in it. And what is the nodeValue
of nothing, of the non-existent object? It is error to try to get something out of nothing, don't you think?
Just use one of the XPath calculators I mentioned, enter there your XML sample and run evaluation for the requests
- //Gordijn[1]/Kamerkant[1]/node()
- //Gordijn[1]/Kamerkant[1]
- //Gordijn[1]/node()
See the difference yourself.
That said, when you use SQL - you have to debug your query and data in some generic non-Delphi SQL tool, and only after that when you got the correct tested SQL request to copy it into your Delphi code.
Same applies to XPath - you better first use XPath calculators to debug XPath requests outside of Delphi and only when succeed you are to replant the tested correct XPath into your Delphi code.
According to
you maybe (depending on variety of ur source data) can use something like
Lclvalue := Sel.Selectnode('//Gordijn[1]/Kamerkant[1]');
if LclValue.hasChildNodes then begin
LclNodes := LclValue.childNodes;
for i := 1 to LclNodes.length do begin
LclValue := LclNodes.item[i];
... process LclValue....
end;
end;
LclValue := nil; // release memory you need no more
LclNodes := nil;
That said, is do not think that is really the most efficient way to do it, it clearly does not fit into set-based XPath worldview. To me it looks like "indexed sequential access method" applied over SQL datasource.
So to me it looks that you do not have to select one node in particular, less so the first node ( those "[1]" in your query - why??? ).
You really try to get the list of ALL the nodes that maybe are interesting to you and prepare for the event there would be none.
For example, the I/O error you get - it MAY (or may not, I do not know, check the docs) be exactly the way of your xml parser to tell "nothing found, empty results".
I open www.google.com and I type there "stackoverflow xpath check if node is empty"
That said, there are different XPath versions and different XPath engines - so whether the XML parser of your code can use those methods only you can determine.
But at very least the following - not very efficient also - seems to be possible;
LclNodes := Sel.Selectnodes('//Gordijn/Kamerkant'); // all the Kamerkants
// MAYBE check for error if XML source has no single Kamerkant,
// i can only GUESS how that maybe would be represented
// you can CHECK it or READ DOCS
for i := 1 to LclNodes.length do begin
// i GUESS LclNodes.length=0 for no Kamerkants data input - i may be badly wrong
LclValue := LclNodes.item[i]; // some Kamerkant
if LclValue.hasChildNodes then begin
LclKamerkantNodes := LclValue.childNodes;
for j := 1 to LclKamerkantNodes.length do begin
LclValue := LclKamerkantNodes.item[j];
... process LclValue....
end;
end;
end;
LclValue := nil; // release memory you need no more
LclKamerkantNodes := nil;
LclNodes := nil;
In the latter code i ASSUME that in general XPath's attitude to SelctNode/SelectNodes is the same as SQL's attitude to singular/general SELECT operation. The former is required to produce exactly 1 row of result, less than 1 or more then 1 are error conditions. The latter gives you a set of rows, that might be empty or might be multiple as well as singular, so you have a flexibility to code for those cases. The former is laconic but fragile with regard to unexpected input data. The latter is much more flexible but also much more tedious and verbose. The choice definitely is yours. But judging from your confusion w.r.t I/O Error - your original choice to use hardcoded singular select maybe was unlucky one.