Author Topic: TFPXMLBridge - TXMLDoument - XML wrapper  (Read 10758 times)

jmpessoa

  • Hero Member
  • *****
  • Posts: 2331
TFPXMLBridge - TXMLDoument - XML wrapper
« on: January 29, 2013, 04:42:29 am »
Hi There,

Here is my attempt to implement a class for working with xml in a more intuitive way.

TXMLBridge class/component handle XML document in a manner not usual, something like easy direct access (read/write/create/remove) to DOM XML nodes by way of namespace like "root.node1.node2.node3"...

Indeed, TXMLBridge class/component is being built on top of already existing FCL-XML parser: XMLRead, XMLWrite, DOM units (TXMLDocument class, TDOMNode class , etc...).


From readme.txt

[1]At the moment this code is just a *proof of concept*

[2]Tokens "Language" :

NamespaceSeparatorToken:  .
BridgeLateBindingToken:  *    //default attribute=0 in late binding
NameValueSeparatorToken:  #  //... equal
AssignmentToken:  $          //... Assignment
ConcatenationToken:  |
AttributeNameValueStartToken:  (
AttributeNameValueEndToken:  )
AttributesSeparatorToken:   ;
IndexStartToken:  [
IndexEndToken:    ]

[3] Sintaxe Example:
3.1.1    Insert item in library.book
library.book(1)$item(id#1;name#lazarus guide)  //sintaxe
library.book(1)                 :namespace where some book attribute=1
$item                           :insert new node item
(id#1;name#lazarus guide)       :with attributes: name1#value1;name2#value2

3.1  Insert item in library.book
library.book$item()out of print    //sintaxe
library.book          :namespace base - first book child
$item                 :insert new node item
()                    :empty open/closed parenthesis: no attribute at all!
out of print          :inner/content text!

3.2  Set value in item(lazarus guide)
library.book.item(lazarus guide)$in stock    //sintaxe
library.book          :namespace base
$in stock            :set item text inner/content/value =in stock

3.3  Set value in author
library.book.item(lazarus guide)author$Mattias Gartner        //sintaxe
library.book.item(lazarus guide)      :namespace base
(                         :open token - attribute
lazarus guide             :item selected by attribute lazarus guide
)                         :close token - attribute
author$Mattias Gartner    :set author text content/inner/value = Mattias Gartner

3.4  : Insert nodes movie and item, after insert coauthor, publisher...
library$movie(id#121).item(id#11;name#2001 A Space Odyssey).author()Stanley Kubrick //sintaxe
library.movie(121).item(11)$coauthor()Arthur C Clarke   //sintaxe
library.movie(121).item(2001 A Space Odyssey)$publisher()Metro Goldwyn Mayer //sintaxe

3.5  Get value by some attribute
library.book(2).item(InstallOverdom help).publisher(B)
library.book(2)            :select book where some attribute=2
item(InstallOverdom help)  :select item where some attribute=InstallOverdom help
publisher(B)               :select publisher where some attribute=B

3.6  Get value by attribute index late binding - handled by OnBuildingBridge
library.book(*).item(*).publisher(*)        :attribute index
  • to all {* = default}

library.book([0]).item([0]).publisher([1])  :attribute index [1] only to publisher

The following code produces  the XML document
which can be seen in figure attached.

Code: [Select]
procedure TForm1.PopupMenu1Close(Sender: TObject);
var
   sText: string;
   newNode, nodeName, attrValue, attrList: string;
   i, countChildren: integer;
   baseNode: TDOMNode;
   basePath, query, bridge, textContent, fileName: string;
begin
    sText:= (Sender as TMenuItem).Caption;
    if CompareText(sText, 'New') = 0 then
    begin
        fileName:= 'hydexon_library_2.xml';
        InputQuery('New','New File', fileName);
        XMLBridge1.CreateXMLDocument(fileName, 'library' {root node});
        XMLBridge1.SaveToFile(fileName);    //just for call Form1 event handler...
    end
    else if CompareText(sText, 'Open') = 0  then
    begin
        fileName:= 'hydexon_library.xml';
        InputQuery('Open','Open File', fileName);
        if not FileExists(fileName) then
           XMLBridge1.CreateXMLDocument('hydexon_library_2.xml', 'library' {root node})
        else
           XMLBridge1.LoadFromFile(fileName);

        XMLDocumentSaved(fileName); //just for call Form1 event handler...
    end
    else if CompareText(sText, 'Insert Node') = 0 then
    begin

         //just dummy information!

          //create on library the nodes: book and item ... pay attention where is the token $
        query:= 'library$book(id#200).item(name#InstallOverdom help).author()Hydexon';
        XMLBridge1.InsertNode(query);

        //insert node coauthor in item... pay attention where is the token $
        query:= 'library.book(200).item(InstallOverdom help)$coauthor()others users';
        XMLBridge1.InsertNode(query);

        query:= 'library.book(200).item(InstallOverdom help)$publisher(id#A;name#git hub)github';
        XMLBridge1.InsertNode(query);
        query:= 'library.book(200).item(InstallOverdom help)$publisher(id#B;name#google)google code';
        XMLBridge1.InsertNode(query);
        query:= 'library.book(200).item(InstallOverdom help)$publisher(id#C;name#media fire)media fire';
        XMLBridge1.InsertNode(query);

       //create on library the nodes: movie and item ... pay attention to the token $
       query:= 'library$movie(id#133).item(id#66;name#2001 A Space Odyssey).author()Stanley Kubrick';
       XMLBridge1.InsertNode(query);

       //insert node coauthor in item... pay attention to the token $
       query:= 'library.movie(133).item(66)$coauthor()Arthur C Clarke';
       XMLBridge1.InsertNode(query);

       //insert node publisher in item... pay attention to the token $
       query:= 'library.movie(133).item(2001 A Space Odyssey)$publisher()Metro Goldwyn Mayer';
       XMLBridge1.InsertNode(query);

       XMLBridge1.SaveToFile(XMLBridge1.XMLDocumentPath);   //just for call Form1 event handler...
    end
    else if CompareText(sText, 'Get Value') = 0 then
    begin
        //query:='library.book(200).item(InstallOverdom help).publisher(B)';
        //query:='library.book(*).item(*).publisher(*)'; {attribute index: [0] = *}
        query:='library.book([0]).item([0]).publisher([1])';  {attribute index: [1] to get publisher}
        ShowMessage(XMLBridge1.GetValue(query));
    end
    else if CompareText(sText, 'Set Value') = 0 then
    begin
        textContent:= 'sourceforge';      //... pay attention to the token $
        query:='library.book(200).item(InstallOverdom help).publisher(C)$'+textContent;
        InputQuery('Set publisher: ','Path:', query);
        XMLBridge1.SetValue(query);
        XMLBridge1.SaveToFile(XMLBridge1.XMLDocumentPath);    //just for call Form1 event handler...
    end
    else if CompareText(sText, 'Remove Node') = 0 then
    begin
        query:='library.book(200).item(InstallOverdom help).publisher(B)';
        InputQuery('Remove publisher: ','Path:', query);
        XMLBridge1.RemoveNode(query);
        XMLBridge1.SaveToFile(XMLBridge1.XMLDocumentPath);    //just for call Form1 event handler...
    end
    else if  CompareText(sText, 'Save') = 0 then
    begin
        XMLBridge1.SaveToFile(XMLBridge1.XMLDocumentPath);
    end
    else if CompareText(sText, 'Exit') = 0 then
    begin
        Application.Terminate;
    end;
end;

I Attached the unit xmlbridge.pas and a demo application, inspired by Hydexon Post:
 
http://www.lazarus.freepascal.org/index.php/topic,19621.0.html

The current implementation is only a proof of concept. Any help and suggestions will be helpful for better and useful implementation...

Greetings and have fun!
« Last Edit: January 29, 2013, 05:15:50 am by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

Hydexon

  • Full Member
  • ***
  • Posts: 170
Re: TFPXMLBridge - TXMLDoument - XML wrapper
« Reply #1 on: January 29, 2013, 05:30:32 am »
Who needs XMLConf, if you can get TFPXMLBridge?.

For me is very useful to create XML human-friendly files!, thanks you!, i hope i can improve your code (specially for the Unicode)
Lazarus 1.0.4 Stable - FPC 2.6.0 - gtk2 | Linux Mint 14 Nadia | GNOME Shell 3.6.2 - Awesome | Intel x86 | HP Mini 1020-LA Netbook (old)
Lazarus 2.0.2 Stable - FPC 3.0.2 - Windows | Lenovo IdeaPad Y

jmpessoa

  • Hero Member
  • *****
  • Posts: 2331
Re: TFPXMLBridge - TXMLDoument - XML wrapper
« Reply #2 on: January 29, 2013, 04:20:36 pm »
Hi, 

You can certainly help a lot!

If you have any questions with the syntax I'm ready to help.

Thank you
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

jmpessoa

  • Hero Member
  • *****
  • Posts: 2331
Re: TFPXMLBridge - TXMLDoument - XML wrapper
« Reply #3 on: February 02, 2013, 09:04:24 pm »
Hi Hydexon,

I put this code in the application demo (insert option) and it worked exactly as you need! The nodes that did not exist were all created!  Please, notice where I put the $ symbol...   

query:= 'library$installoverdomproject.installationdata.applicationdata.appname()MyApp';
XMLBridge1.InsertNode(query);

Document result:

<?xml version="1.0" encoding="utf-8"?>
<library>
  <installoverdomproject>
    <installationdata>
      <applicationdata>
        <appname>MyApp</appname>
      </applicationdata>
    </installationdata>
  </installoverdomproject>
</library>     ]
 

Thank you!

Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

jmpessoa

  • Hero Member
  • *****
  • Posts: 2331
Re: TFPXMLBridge - TXMLDoument - XML wrapper
« Reply #4 on: February 10, 2013, 09:44:33 pm »
Hi All,

TFPXMLBridge new component now is in github

https://github.com/jmpessoa/tfpxmlbridge

TXMLBridge class/component handle XML document in a manner not usual, something like easy direct access (read/write/create/remove) to DOM XML nodes by way of namespace like "root.node1.node2.node3"...

Indeed, TXMLBridge class/component is being built on top of already existing FCL-XML parser: XMLRead, XMLWrite, DOM units (TXMLDocument class, TDOMNode class , etc...).

From readme.txt

TFPXMLBridge - Version 0.1 - 01/2013;

Author: Jose Marques Pessoa : jmpessoa__hotmail_com
[1]Warning: at the moment this code is just a *proof-of-concept*

::revision 01 - 09/February/2013

NEW Sintaxe GetValue/SetValue by Node Index.
NEW procedure SetCurrentNode(query: string).
NEW change AppDemo1    (remove option "new documment")
NEW Add    AppDemo2    (here is the option "new documment")
NEW Tips..

[2]Tokens "Language" :
Warning: change this tokens if necessary... or Application will crash!

NamespaceSeparatorToken:  .
BridgeLateBindingToken:  *    //default attribute=0 in late binding
NameValueSeparatorToken:  #  //... equal
AssignmentToken:  $          //... Assignment
ConcatenationToken:  |
AttributeNameValueStartToken:  (
AttributeNameValueEndToken:  )
AttributesSeparatorToken:   ;
IndexStartToken:  [
IndexEndToken:    ]

[3] Sintaxe Example:

3.1.0

    //take library as the root node:

    <?xml version="1.0" encoding="utf-8"?>
    <library>
    </library>

    Now, after the commands:

    InsertNode('library$book(id#100)')  //create node <book id="100">
    InsertNode('library$book(id#200)')  //create node <book id="200">

    the documment is:

    <?xml version="1.0" encoding="utf-8"?>
    <library>
         <book id="100">
         </book>
         <book id="200">
         </book>
    </library>

3.1.1    Insert item in library.book(100)           //library is root node
library.book(100)$item(id#1;name#lazarus guide)  //sintaxe
library.book(100)                 :namespace where some book attribute=100
$item                           :insert new node item
(id#1;name#lazarus guide)       :with attributes: name1#value1;name2#value2

3.1  Insert item in library.book
library.book$item()out of print    //sintaxe
library.book          :namespace base - first book child
$item                 :insert new node item
()                    :empty open/closed parenthesis: no attribute at all!
out of print          :inner/content text!

3.2  Set value in item(lazarus guide)
library.book(100).item(lazarus guide)$in stock    //sintaxe
library.book(100)          :namespace base
$in stock            :set item text inner/content/value =in stock

:TIP 1 {InsertNode}: The path to the left of the token "$" must already exist!
:TIP 2 {InsertNode}: If the right path of the token "$" not exists will be fully created!

3.3  Set value in author
library.book(100).item(lazarus guide)author$Mattias Gartner        //sintaxe
library.book(100).item(lazarus guide)      :namespace base
(                         :open token - attribute
lazarus guide             :item selected by attribute lazarus guide
)                         :close token - attribute
author$Mattias Gartner    :set author text content/inner/value = Mattias Gartner

:TIP 3 {SetValue}: Note that the symbol "$" is always placed at the end of the path
                   where you need/want to Set the value!

3.4  Generic Insert example: Insert nodes movie and item... then insert coauthor, publisher...
library$movie(id#121).item(id#11;name#2001 A Space Odyssey).author()Stanley Kubrick //sintaxe
library.movie(121).item(11)$coauthor()Arthur C Clarke   //sintaxe
library.movie(121).item(2001 A Space Odyssey)$publisher()Metro Goldwyn Mayer //sintaxe

3.5  Generic Get example: Get value by some attribute
library.book(200).item(InstallOverdom help).publisher(B)
library.book(200)            :select book where some attribute=2
item(InstallOverdom help)  :select item where some attribute=InstallOverdom help
publisher(B)               :select publisher where some attribute=B

3.6 Generic GetValue by nodeIndex:

        //library is root node

        InsertNode('library$stationery') //create node <stationery>

        InsertNode('library.stationery$item()pencil') //create node <item>pencil</item>
        InsertNode('library.stationery$item()pen') //create node <item>pen</item>
        InsertNode('library.stationery$item()eraser') //create node <item>eraser</item>
        InsertNode('library.stationery$item()notebook') //create node <item>notebook</item>

        //this code read each item value...by index!
        query:='library.stationery';
        count:= FPXMLBridge1.CountElementNodeChildren(FPXMLBridge1.GetNode(query));
        for i:=0 to count-1 do
        begin;
          query:= 'library.stationery.item['+intToStr(i)+']';
          ShowMessage(FPXMLBridge1.GetValue(query));
        end;

3.7 Generic SetValue by node index:

        //this code (re)write each item value...by index!
        query:='library.stationery';
        count:= FPXMLBridge1.CountElementNodeChildren(FPXMLBridge1.GetNode(query));
        for i:=0 to count-1 do
        begin;
          query:= 'library.stationery.item['+intToStr(i)+']'+'$'+intToStr(i*100);
          FPXMLBridge1.SetValue(query);
          FPXMLBridge1.SaveToFile(FPXMLBridge1.XMLDocumentPath);
        end;

3.8 Select path to go "on the fly": Get value by attribute index late binding - handled by OnBuildingBridge
library.book(*).item(*).publisher(*)        :select attribute index =
  • to all {default}

library.book([0]).item([0]).publisher([1])  :select attribute index = [1] only to publisher...

[4]Have fun!
« Last Edit: February 10, 2013, 11:04:36 pm by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

jmpessoa

  • Hero Member
  • *****
  • Posts: 2331
Re: TFPXMLBridge - TXMLDoument - XML wrapper
« Reply #5 on: February 11, 2013, 05:09:07 am »
Here is the stuff in "rar" format... (Attachment)

Greetings!
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

jmpessoa

  • Hero Member
  • *****
  • Posts: 2331
Re: TFPXMLBridge - TXMLDoument - XML wrapper
« Reply #6 on: February 25, 2013, 01:50:39 am »
Hi there!

TFPXMLBridge component revision 02 now suport read/write Attributes

   NEW function GetAttrList(query: string): string;   
   NEW function GetAttrValueByName(query: string; attrName: string)
   NEW procedure SetAttribute(query: string)
   NEW Add    AppDemo3

Sintaxe example:

This code produce XML Document as seen in the  picture tfpxmlbridge_demo3_screen_1.png (Attachment)
Code: [Select]
     FPXMLBridge1.CreateXMLDocument('projStructural.xml', 'project');

     query:= 'project$beams';
     FPXMLBridge1.InsertNode(query);

     query:= 'project.beams$beam(id#1)';
     FPXMLBridge1.InsertNode(query);

     query:= 'project.beams.beam(1)$spans';
     FPXMLBridge1.InsertNode(query);

     query:= 'project.beams.beam(1).spans$span(len#5,5;q#1000)';
     FPXMLBridge1.InsertNode(query);

     query:= 'project.beams.beam(1).spans$span(len#4,5;q#1200)';
     FPXMLBridge1.InsertNode(query);

And this code produces the modified XML Document as seen in the picture tfpxmlbridge_demo3_screen_2.png (Attachment)
Code: [Select]
      query:= 'project.beams.beam(1).spans.span[0]$loadp(offset#2,7;p#200)';
      FPXMLBridge1.InsertNode(query);

      query:= 'project.beams.beam(1).spans.span[1]$loadp(offset#3,2;p#400)';
      FPXMLBridge1.InsertNode(query);


      query:= 'project.beams.beam(1).spans.span[0]$(id#1)';
      FPXMLBridge1.SetAttribute(query);

      query:= 'project.beams.beam(1).spans.span[1].loadp[0]$(p#444)';
      FPXMLBridge1.SetAttribute(query);

The full stuff follows attached in "rar" format...
or https://github.com/jmpessoa/tfpxmlbridge

Greetings!
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

jmpessoa

  • Hero Member
  • *****
  • Posts: 2331
Re: TFPXMLBridge - TXMLDoument - XML wrapper
« Reply #7 on: August 31, 2013, 07:04:42 pm »
Hi There!

The TFPXMBridge packge now include 

a new component:  TreeViewXmlBridge (and an AppDemo)

a two-ways (read/write) tools for xml handling in treeview....

The complete stuff is here: 

https://github.com/jmpessoa/tfpxmlbridge

See attachments  for Demo picture...

Greetings!

« Last Edit: August 31, 2013, 09:21:45 pm by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

 

TinyPortal © 2005-2018