0

this is my xml file (content.xml):

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   <head></head>
   <body>
      <h1>Lorem ipsum dolor sit amet</h1>
  </body>
</html>

that is my code in Delphi (XE5):

procedure TForm1.Button1Click(Sender: TObject);
var
 doc: IXMLDocument;
 Sel: IDOMNodeSelect;
 List : IDOMNodeList;
 query: String;
 begin
   content := TFile.ReadAllText('C:\temp\content.xml');
   doc := TXMLDocument.Create(Application);
   doc.LoadFromXML(content);
   doc.Active := True;
   query := '//descendant::html';
   Sel := doc.DOMDocument as IDomNodeSelect;
   List := Sel.selectNodes(query);
  // List.length is 0 !!!!
end;

The question why List is empty, shoud contain four elements: HTML, head, body, h1(that's "html" tag and all its children. According to http://www.w3schools.com/xpath/xpath_syntax.asp XPath syntax I've tried that options:

//html/* 
/html
/html/*

none of them Works for me so at this point I do not know if the query is ok or my code fails in another point.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
user3779155
  • 101
  • 8
  • Surely a duplicate therefore I strongly doubt that this won't be downvoted/closed. In the meantime take a look at [this](http://stackoverflow.com/questions/5383919/xpath-and-txmldocument). – mg30rg Oct 13 '14 at 14:54
  • [Finding elements with XPath in Delphi](http://stackoverflow.com/questions/1406138/finding-elements-with-xpath-in-delphi) – bummi Oct 13 '14 at 15:12
  • Hi, thanks for your answer, I've tried right now, but not working, first I am using IDomNode and I need to get IDOMNodeList and also I would like that the query Works because follows XPath Syntax from W3S. – user3779155 Oct 13 '14 at 15:29
  • Hi bummi, I am using this http://theroadtodelphi.wordpress.com/2013/05/29/enabling-xpath-selectnode-selectnodes-methods-in-vcl-and-firemonkey-apps/ and as you can see my example is almost the same, but still not working. – user3779155 Oct 13 '14 at 15:39

3 Answers3

3

You seem to use MSXML with Delphi so you need to make sure you first call

doc.setProperty('SelectionLanguage', 'XPath')

then set

doc.setProperty('SelectionNamespaces', 'xmlns:xhtml="http://www.w3.org/1999/xhtml"')

and finally you need to use that prefix xhtml anywhere you want to qualify elements e.g.

doc.selectNodes('//xhtml:h1')

selects all h1 elements.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
0

I would suggest NOT using TFile.ReadAllText() in this situation. Let TXMLDocument load the file directly, then you don't have to deal with any encoding issues.

You can get rid of doc.LoadFromXML() and set the doc.FileName property instead:

procedure TForm1.Button1Click(Sender: TObject);
var
  doc: TXMLDocument;
  ...
begin
  doc := TXMLDocument.Create(Application);
  try
    doc.FileName := 'C:\temp\content.xml';
    doc.Active := True;
    ...
  finally
    doc.Free;
  end;
end;

Or you can or replace TXMLDocument with the LoadXMLDocument() function, which takes a filename as input:

procedure TForm1.Button1Click(Sender: TObject);
var
  doc: IXMLDocument;
  ...
begin
  doc := LoadXMLDocument('C:\temp\content.xml');
  ...
end;

Either way, then you can deal with the XPath query as Martin Honnen suggested.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
-1

After hours the error was really simple, the "content" variable has to be AnsiString NOT String. XPath was right, but not the variable.

That's wrong

var
 content: String;// WRONG should be content: AnsiString;
 begin
  content := TFile.ReadAllText('C:\temp\content.xml');
  doc := TXMLDocument.Create(Application);
  doc.LoadFromXML(content);
  doc.Active := True;

 end;

I was looking at the wrong place: Query Variable and XPath Syntax.

user3779155
  • 101
  • 8
  • 1
    `List.length is 0 !!!!` as before, I don't see how this can be the answer, the main problem, the namespace is not handled. Even the declaration of content was not shown in the question. – bummi Oct 13 '14 at 17:25
  • I would suggest NOT using `TFile.ReadAllText()` in this situation. Let `TXMLDocument` load the file directly. Get rid of `doc.LoadFromXML()` and set the `doc.FileName` property instead, or replace the `TXMLDocument` component with the `LoadXMLDocument()` function, which takes a filename as input. – Remy Lebeau Oct 14 '14 at 00:37