Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2011-03

TDOMElement and multiple attributes

10 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Reimar Grabowski

Hi all,

I want to create a node with multiple attributes. It works by using SetAttribute multiple times but it looks like I cannot specify the order in which the attributes appear in the xml. The order of my SetAttribute calls has no influence on the order in the node. So my question is if there is a way to specify which attribute is the first, second and so on?

R.

A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing in e-mail?

Reply by email

Mattias Gaertner
to Reimar Grabowski
Hi all, I want to create a node with multiple attributes. It works by using SetAttribute multiple times but it looks like I cannot specify the order in which the attributes appear in the xml. The order of my SetAttribute calls has no influence on the order in the node. So my question is if there is a way to specify which attribute is the first, second and so on?

The attributes are a set of name, value pairs. There is no order. xml parsers must work with any order.
Why do you need to order them?

Mattias

Reply by email

Reimar Grabowski
to Mattias Gaertner
Why do you need to order them?

I don't need to, I just want to and the reason is simply aesthetics. So no big deal that it is not possible. Btw is there any comprehensible reason behind the order which SetAttribute uses? It is not alphabetical and not the order of the SetAttribute calls.

R.

A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing in e-mail?

Reply by email

Unknown author
to Reimar Grabowski
Reimar Grabowski wrote 6 lines
On Fri, 18 Mar 2011 16:02:10 +0100 Mattias Gaertner wrote: > Why do you need to order them? I don't need to, I just want to and the reason is simply aesthetics. So no big deal that it is not possible. Btw is there any comprehensible reason behind the order which SetAttribute uses? It is not alphabetical and not the order of the SetAttribute calls.

Probably determined by hashvalue or the AVL tree order.

Michael.

Reply by email

Reimar Grabowski
to Unknown author
Probably determined by hashvalue or the AVL tree order.

That makes sense, thank you for the info.

R.

A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing in e-mail?

Reply by email

Mattias Gaertner
to Unknown author: Probably determined by hashvalue or the AVL tree order. Michael.
Show quoted text 12 lines
On Fri, 18 Mar 2011, Reimar Grabowski wrote: > On Fri, 18 Mar 2011 16:02:10 +0100 > Mattias Gaertner wrote: > >> Why do you need to order them? > I don't need to, I just want to and the reason is simply aesthetics. So no big deal that it is not possible. > Btw is there any comprehensible reason behind the order which SetAttribute uses? It is not alphabetical and not the order of the SetAttribute calls. Probably determined by hashvalue or the AVL tree order.

No.
TDOMNamedNodeMap does not use hash nor AVL tree.
It uses a binary search in TDOMNamedNodeMap.Find to find the insert position, so it should be alphabetically sorted.
On a first glance the code looks ok.
Maybe Reimar can give an example when it does not work.

Mattias

Reply by email

Reimar Grabowski
to Mattias Gaertner
Maybe Reimar can give an example when it does not work.

I am to lazy to attach the code, so here it is (you should know how to get it into Lazarus without too much hassle :) ):

program xmlattributes;
{$mode objfpc}{$H+}
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, SysUtils, CustApp,
  DOM, XMLWrite;
type
  { TXMLAttributes }
  TXMLAttributes = class(TCustomApplication)
  protected
    procedure DoRun; override;
  public
  end;

{ TXMLAttributes }

procedure TXMLAttributes.DoRun;
var
  ErrorMsg: String;
  Document: TXMLDocument;
  RootNode, Node: TDOMNode;
begin
  try
    Document:=TXMLDocument.Create;
    RootNode:=Document.CreateElement('ROOT');
    TDOMElement(RootNode).SetAttribute('someAttrib', 'someValue');
    Document.AppendChild(RootNode);
    RootNode:=Document.DocumentElement;
    Node:=Document.CreateElement('SomeNode');
    TDOMElement(Node).SetAttribute('aaaAttribute', '1');
    TDOMElement(Node).SetAttribute('aAttribute', '2');
    TDOMElement(Node).SetAttribute('ccAttribute', '4');
    TDOMElement(Node).SetAttribute('bAttribute', '3');
    RootNode.Appendchild(Node);
    WriteXMLFile(Document, 'test.xml');
  finally
    Document.Free;
  end;
  // stop program loop
  Terminate;
end;
var
  Application: TXMLAttributes;
{$R *.res}
begin
  Application:=TXMLAttributes.Create(nil);
  Application.Title:='XMLAttributes';
  Application.Run;
  Application.Free;
end.

cat test.xml
<?xml version="1.0"?>
<ROOT someAttrib="someValue">
<SomeNode aAttribute="2" bAttribute="3" ccAttribute="4" aaaAttribute="1"/> </ROOT>

Looks like the order is governed by the length of the attribute name first and then alphabetically.

R.

A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing in e-mail?

Reply by email

Mattias Gaertner
to Reimar Grabowski
Show quoted text 65 lines
[...] I am to lazy to attach the code, so here it is (you should know how to get it into Lazarus without too much hassle :) ): program xmlattributes; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, SysUtils, CustApp, DOM, XMLWrite; type { TXMLAttributes } TXMLAttributes = class(TCustomApplication) protected procedure DoRun; override; public end; { TXMLAttributes } procedure TXMLAttributes.DoRun; var ErrorMsg: String; Document: TXMLDocument; RootNode, Node: TDOMNode; begin try Document:=TXMLDocument.Create; RootNode:=Document.CreateElement('ROOT'); TDOMElement(RootNode).SetAttribute('someAttrib', 'someValue'); Document.AppendChild(RootNode); RootNode:=Document.DocumentElement; Node:=Document.CreateElement('SomeNode'); TDOMElement(Node).SetAttribute('aaaAttribute', '1'); TDOMElement(Node).SetAttribute('aAttribute', '2'); TDOMElement(Node).SetAttribute('ccAttribute', '4'); TDOMElement(Node).SetAttribute('bAttribute', '3'); RootNode.Appendchild(Node); WriteXMLFile(Document, 'test.xml'); finally Document.Free; end; // stop program loop Terminate; end; var Application: TXMLAttributes; {$R *.res} begin Application:=TXMLAttributes.Create(nil); Application.Title:='XMLAttributes'; Application.Run; Application.Free; end.

Thanks.

Show quoted text 7 lines
cat test.xml <?xml version="1.0"?> <ROOT someAttrib="someValue"> <SomeNode aAttribute="2" bAttribute="3" ccAttribute="4" aaaAttribute="1"/> </ROOT> Looks like the order is governed by the length of the attribute name first and then alphabetically.

Yes, that is what CompareDOMStrings does.
Probably for speed reasons.
This function is fixed in the code.

Mattias

Reply by email

Flávio Etrusco
to Mattias Gaertner
Show quoted text 10 lines
> cat test.xml > <?xml version="1.0"?> > <ROOT someAttrib="someValue"> >   <SomeNode aAttribute="2" bAttribute="3" ccAttribute="4" aaaAttribute="1"/> > </ROOT> > > Looks like the order is governed by the length of the attribute name first and then alphabetically. >

Actually it isn't sorted by length, but it's case-sensitive.

Mattias wrote
Yes, that is what CompareDOMStrings does. Probably for speed reasons.

Indeed, laz_xmlwrite and laz2_xmlwrite both do this, but the example is using xmlwrite.pas from fcl-xml.

This function is fixed in the code.

What do you mean?

Best regards.
Flávio

Reply by email

Mattias Gaertner
to Flávio Etrusco
Show quoted text 11 lines
> > >> cat test.xml >> <?xml version="1.0"?> >> <ROOT someAttrib="someValue"> >>   <SomeNode aAttribute="2" bAttribute="3" ccAttribute="4" aaaAttribute="1"/> >> </ROOT> >> >> Looks like the order is governed by the length of the attribute name first and then alphabetically. >> Actually it isn't sorted by length, but it's case-sensitive.

No. See

2.4.2/fpc/packages/fcl-xml/src/dom.pp

function CompareDOMStrings(const s1, s2: DOMPChar; l1, l2: integer):
integer;
var i: integer;
begin
  Result:=l1-l2;
  i:=0;
  while (i<l1) and (Result=0) do begin
    Result:=ord(s1[i])-ord(s2[i]);
    inc(i);
  end;
end;
Show quoted text 6 lines
Mattias wrote: > Yes, that is what CompareDOMStrings does. > Probably for speed reasons. > Indeed, laz_xmlwrite and laz2_xmlwrite both do this, but the example is using xmlwrite.pas from fcl-xml.

No. laz_xmlwrite and laz2_xmlwrite use laz_dom, laz2_dom.

> This function is fixed in the code. > What do you mean?

The user can not change this behavior.

Mattias

Reply by email