TDOMElement and multiple attributes

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

TDOMElement and multiple attributes

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?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TDOMElement and multiple attributes

Mattias Gaertner
On Fri, 18 Mar 2011 15:42:13 +0100
Reimar Grabowski <[hidden email]> wrote:

> 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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TDOMElement and multiple attributes

Reimar Grabowski
On Fri, 18 Mar 2011 16:02:10 +0100
Mattias Gaertner <[hidden email]> 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.

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?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TDOMElement and multiple attributes

michael.vancanneyt


On Fri, 18 Mar 2011, Reimar Grabowski wrote:

> On Fri, 18 Mar 2011 16:02:10 +0100
> Mattias Gaertner <[hidden email]> 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.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TDOMElement and multiple attributes

Reimar Grabowski
On Fri, 18 Mar 2011 17:08:49 +0100 (CET)
[hidden email] wrote:

> 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?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TDOMElement and multiple attributes

Mattias Gaertner
In reply to this post by michael.vancanneyt
On Fri, 18 Mar 2011 17:08:49 +0100 (CET)
[hidden email] wrote:

>
>
> On Fri, 18 Mar 2011, Reimar Grabowski wrote:
>
> > On Fri, 18 Mar 2011 16:02:10 +0100
> > Mattias Gaertner <[hidden email]> 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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TDOMElement and multiple attributes

Reimar Grabowski
On Fri, 18 Mar 2011 20:16:08 +0100
Mattias Gaertner <[hidden email]> wrote:

> 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.

someone@somewhere:~/pascal/Projects/xmldemo$ 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?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TDOMElement and multiple attributes

Mattias Gaertner
On Mon, 21 Mar 2011 15:34:28 +0100
Reimar Grabowski <[hidden email]> wrote:

>[...]
> 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.

 
> someone@somewhere:~/pascal/Projects/xmldemo$ 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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TDOMElement and multiple attributes

etrusco
>
>
>> someone@somewhere:~/pascal/Projects/xmldemo$ 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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TDOMElement and multiple attributes

Mattias Gaertner
On Sun, 27 Mar 2011 22:56:16 -0300
Flávio Etrusco <[hidden email]> wrote:

> >
> >
> >> someone@somewhere:~/pascal/Projects/xmldemo$ 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;


> 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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal