tags:

views:

648

answers:

4

Hi. I am trying to find an element in an XML document in Delphi. I have this code, but it always says 0 elements in the log:

function TForm1.KannaSidu: Boolean;
var
  Doc: IXMLDOMDocument; 
  List: IXMLDomNodeList;
begin
  try
    Doc := CreateOleObject('Microsoft.XMLDOM') as IXMLDomDocument;
    Doc.async:=False;
    Doc.load(Filename);
  except
    LogTx('Error on page');
  end;
  List:=Doc.selectNodes('/html/head');
  LogTx(IntToStr(List.length)+' elements');
  Result:=False;
end;

So how do I make XPath work?

A: 

Any possibility you need to escape the / ?

Toby Allen
No, it is Delphi.
Lars Truijens
+1  A: 

In the example code I find online for the selectNodes method, it is preceded by code that sets the document's SelectionNamespaces property via setProperty. Some even set SelectionLanguage, too.

Doc.setProperty('SelectionLanguage', 'XPath');
Doc.setProperty('SelectionNamespaces',
  'xmlns:xsl=''http://www.w3.org/1999/XSL/Transform''');

Based on the element names you're searching for, I guess you're processing an HTML file. The basic HTML elements are in the http://www.w3.org/1999/xhtml namespace, so try this:

Doc.setProperty('SelectionNamespaces',
  'xmlns:x=''http://www.w3.org/1999/xhtml''');
List := Doc.selectNodes('/x:html/x:head');

See also:

selectNodes does not give node list when xmlns is used on Microsoft's forum.

Rob Kennedy
I don't think it is the reason here. Moreover setProperty only exists in IXMLDOMDocument2, not in IXMLDOMDocument.
François
+1  A: 

IXMLDOMDocument.Load() does not raise an exception if something goes wrong with you file or with its content. Try the following to be sure there is nothing bad with it :

...
Doc.load(Filename);
if Doc.parseError.errorCode <> 0 then
  ShowMessage('Error : ' + + Doc.parseError.reason) 
else
  ShowMessage('No problem so far !');
...

I suck at XPath but mabe if html is your root node you don't need to include it in your query string, so try the following :

List:=Doc.selectNodes('//html/head');

or

List:=Doc.selectNodes('//head');
Fred
+2  A: 

If you're just trying to load a plain html file as xml, it would probably have multiple reasons to fail and choke on things like:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;

You have to test that it actually loads correctly before doing anything else:

  if not Doc.load(filename) then
    raise Exception.Create('XML Loading error:' + Trim(Doc.parseError.reason));

It will give you the specific reason for the failure like this one:

XML Loading error:End tag 'head' does not match the start tag 'link'.
François
This was very helpful for me, parseError caught an ID10T error on my part.
Chris Miller