Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 9 of 9 total
Thread XML
Thu, Feb 7 2013 7:20 AMPermanent Link

Matthew Jones

I need to parse XML. The data that I will be getting via an https JSON interface
has to include an XML packet. Well, I guess I could put the smarts in the server,
but I'd really rather not. This doesn't appear to be too common looking back at the
newsgroups (I can't find anything), but there does seem to be some sort of support
in that TXMLHttpRequest deals with a TDocument. I can't find that in the source, so
it must be intrinsic somehow. So I knocked up this code:

procedure TfrmTest.ParseXML(szXML : String);
var
   xDocument : TDocument;
begin                     
   xDocument := TDocument.Create;
   try                       
       xDocument.LoadXML(szXML);
   finally
       xDocument.Free;
   end;
   
end;

When I run it, it gives a "Document not defined" error in the IDE, and in Chrome it
gives "Uncaught TypeError: Illegal constructor". The code appears to be:

fclicker_tfrmclicker.$p.tfrmclicker_parsequestionxml = function(szxml)
{
  var $t = this, xdocument;
  xdocument = new Document();
  try
  {
     xdocument.loadXML(szxml);
  }
  finally
  {
     xdocument = null;
  }
};

Is it that my lack of JavaScript knowledge is showing here? 8-)
Is there a way to parse XML that I can use? Or do I have to write my own parser?

http://www.w3schools.com/xml/xml_parser.asp indicates that I should be able to
create a DOMParser. How might I access it please?

(Oh, and I'd really like "FreeAndNil" as I use it all the time out of habit.)

/Matthew Jones/
Thu, Feb 7 2013 3:09 PMPermanent Link

Claudia Borsel


In webdom.wbs is a comment: (// IE-only) which explains the Chrome-Browser behaviour:

  external TDocument = class(TNode)
     public
           procedure loadXML(const text: String); // IE-only

but then it should at least work in the IDE, which is based on IE. So I also don't know...
Thu, Feb 7 2013 4:37 PMPermanent Link

Claudia Borsel

If you add the attached xmldocu.js to the external code in the project manager, then the following code does, what you want to do.

___________________________
unit Unit1;

interface

uses WebForms, webctrls, WebDom;

type

  TForm1 = class(TForm)
     Button1: TButton;
     Memo1: TMemo;
     procedure Button1Click(Sender: TObject);
  private
     { Private declarations }
  public
     { Public declarations }
  end;

external function getDOMfromXMLstring(const txt: String): TDocument;

var
  Form1: TForm1;

implementation

procedure TForm1.Button1Click(Sender: TObject);
var
  szXML: string;
  respDoc: TDocument;
  i: integer;
  datanodeliste  : TNodeList;
begin
  szXML := '<a><b><c><username>testuser</username></c></b></a>';
  respDoc := getDOMfromXMLstring(szXML);
  datanodeliste := respDoc.getElementsByTagName('username');
  for i := 0 to datanodeliste.length-1 do
   begin
     memo1.lines.add(datanodeliste[i].nodeName);
     memo1.lines.add(datanodeliste[i].textContent);
  end;

end;
end.
________________________________________

It works in Opera and FF and Chrome flawlessy, but somehow the .textContent part does not work in IE, and therefore also not in the EWB-IDE.



Attachments: xmldocu.js
Fri, Feb 8 2013 12:03 PMPermanent Link

Matthew Jones

Thanks - will review when I get back properly (have been out driving for a day or
two).

/Matthew Jones/
Mon, Feb 11 2013 8:30 AMPermanent Link

Matthew Jones

> It works in Opera and FF and Chrome flawlessy, but somehow the
> .textContent part does not work in IE, and therefore also not in
> the EWB-IDE.

As you say, IE doesn't work. I can research that though, thank you very much.

When I run it in Chrome, it doesn't know the external function - presumably I have
to put the .js somewhere. I will look at that too. Hmm, EWB has put it in the
output directory, and the .html refers to it as a script before the EWB output
script. The case of the names matches. I must be missing something. Hmm, Chrome is
showing an error for the xml. Right, it has three nul bytes at the end (zeros).
Quick hack of that and it works fine. Must have been a decode issue from my NNTP
client.

[later]
After reading many books, studying hard, and mastering the Javascript language and
all the various browser variations [or googling it, whichever was easiest] I found
http://stackoverflow.com/questions/10804442 which shows that in IE you have to use
nodeValue. They have a
function getText(el) {
 return el.textContent || el.innerText || el.nodeValue || '';
}
which appends the various possible names together, and discusses the undefined, but
nodeValue appears to work in both IE and Chrome.

/Matthew Jones/
Thu, Feb 14 2013 11:35 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< I need to parse XML. The data that I will be getting via an https JSON
interface has to include an XML packet. Well, I guess I could put the smarts
in the server, but I'd really rather not. This doesn't appear to be too
common looking back at the newsgroups (I can't find anything), but there
does seem to be some sort of support in that TXMLHttpRequest deals with a
TDocument. I can't find that in the source, so it must be intrinsic somehow.
>>

I'll need to add some support for this because it requires some hoop-jumping
to get around the fact that IE and "the others" use different techniques.

<< (Oh, and I'd really like "FreeAndNil" as I use it all the time out of
habit.) >>

Sorry, but there's no variable parameter support in EWB.  However, Free
works automatically just like FreeAndNil using some compiler tricks, so no
worries.

Tim Young
Elevate Software
www.elevatesoft.com
Thu, Feb 14 2013 2:45 PMPermanent Link

Matthew Jones

> I'll need to add some support for this because it requires some
> hoop-jumping to get around the fact that IE and "the others" use
> different techniques.

The code Claudia gave appears to work in IE and Chrome for me.

/Matthew Jones/
Thu, Feb 14 2013 3:21 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< The code Claudia gave appears to work in IE and Chrome for me. >>

Sure, but XML handling is "core work", and should be in the framework (no
offense to Claudia, whose solution was excellent).

I added two things:

1) There's now a new CreateActiveXObject function (built-in) that can be
used for instantiating ActiveX objects in IE.
2) I added this function to the WebDOM unit:

function ParseXML(const Value: String): TDocument;
var
  TempParser: TDOMParser;
begin
  if IsIE then
     begin
     Result:=TDocument(CreateActiveXObject('Microsoft.XMLDOM'));
     Result.LoadXML(Value);
     end
  else
     begin
     TempParser:=TDOMParser.Create;
     try
        Result:=TempParser.parseFromString(Value,'text/xml');
     finally
        TempParser.Free;
     end;
     end;
end;

And so, you can use it like this:

procedure TForm2.Button3Click(Sender: TObject);
var
  TempXML: String;
  TempDocument: TDocument;
  TempNodes: TNodeList;
begin
  TempXML:='<a><b><c><username>testuser</username></c></b></a>';
  TempDocument:=ParseXML(TempXML);
  TempNodes:=TempDocument.getElementsByTagName('username');
  ShowMessage(IntToStr(TempNodes.length)); // Number of nodes
  ShowMessage(TempNodes[0].firstChild.nodeValue); // Get text node, returns
'testuser'
end;

This is a lot cleaner than having to include external JS, and works
similarly to the ParseXML method of the TServerRequest class.

Tim Young
Elevate Software
www.elevatesoft.com
Fri, Feb 15 2013 4:09 AMPermanent Link

Matthew Jones

Look forward to it.

/Matthew Jones/
Image