[Gambas-user] XML library with xml multilevel tags

Luigi Carlotto md9327 at ...120...
Sun Dec 28 02:14:04 CET 2008


Il giorno sab, 27/12/2008 alle 20.04 +0100, Luigi Carlotto ha scritto:

> I do not comprise the reason, but mine precedence post has been
> included like answer in an other mail.
> 
> … however…
> 
> 
> Gambas 2.9.0
> 
> Using the gb.xml library, me they are shrewed that the reading can be
> carried out single on files xml to 2 levels.
> I explain myself in better way…
> I have necessity to read xml files, that it contains a composed
> structure from elements, structured in hierarchical way on more
> levels, as an example:
> 
> <?xml version="1.0" encoding="UTF8"?>
> <pgDesigner Version="2.0.0">
> <PROJECT Name="bible" PageFormat="A4" PageOrientation="0"
> Revision="14/03/2008 14:44:03" Description="bible" Driver="8.2"
> Author="mgm" Display="0">
>   <TABLE Name="tb_log" X="10" Y="6" ColorBack="230,230,230"
> ColorText="0,0,0" ColorBackTitle="230,230,230"
> ColorBackTitleSelected="76,89,166" ColorForeTitle="0,0,0"
> ColorForeTitleSelected="255,255,255" Comment="006C006F0067"
> Option="false" PrimaryKey="tb_log_pk">
>     <TABLEFIELD Name="id" Table="tb_log"
> Comment="006900640065006E00740069006600690061006E0074" Length="0"
> NullCheck="true" PrimaryKey="true" Type1="serial"/>
>     <INDEX Name="tb_type_personne_idx1" Table="tb_type_personne"
> Unique="true"/>
>   </TABLE>
> questa è una prova
> </PROJECT>
> </pgDesigner>
> 
> In the example, the hierarchy of the rows xml is composed gives:
> 1) a main element (root) “<pgDesigner>”;
> 2) inside of the root, the element is present “<PROJECT>”;
> 3) under “<PROJECT>” the element is present “<TABLE>”;
> 4) in its turn, the element “<TABLE>” contains a series of other
> heterogenous elements.
> 
> Through the gb.xml library, the reading of the file does not notice of
> the closing of tag (Node.Type=XmlReaderNodeType.EndElement), if these
> are sluices on the same definition of the tag, like as an example:
> 
> <INDEX Name="tb_type_personne_idx1" Table="tb_type_personne"
> Unique="true"/>
> 
> the reading evidences the opening of tag, but the not its closing, for
> which it renders impossible to ago understand if tag following the
> part of a advanced element, or is to the same level of the element
> precedence.
> 
> The behavior is various in phase of writing where, through the methods
> “StartElement” and “EndElement”, it is possible to define complex
> structures.
> 
> This logic, currently, only forces the use of structures xml on two
> levels.


The spaces contained in the strings do not have particolary functions,
but they make part of the name of the object, and it is not possible to
eliminate them.
In other cases, use the comma in order to separate a list of elements
(es. an Array, Join function), than in reading comes reconverted in
Array (Split function).

With regard to the levels, I have resolved, constructing a series of
classes, based on the objects XmlReader and XmlWriter.
Logic of these objects allows to only read to rows xml multilevel, but
if the tag they are not sluices on if same. In contrary case, the gb.xml
library does not notice of the closing of the tag, for which the
hierarchy it does not come constructed in correct way.

These classes directly work in memory, loading the xml files in a
structure, that it can be read inside of a program.
The writing comes carried out through the same structure of memory.
This logic me slightly seems or faster, and fastly releases the
connections to the file.

Only problem, perhaps, could be the management of large files; I have
tried with xml of 2Mbyte, and I am fast.
Perhaps he can be useful in Gambas…
The structure follows logic, also applied in other languages, than part
from an object Document (pgXmlDocument), that a Root element contains;
like then for all the other elements (pgXmlElement), it contains an
Array of elements and an Array of attributes (pgXmlAttribute).
The connection with the object father, comes managed from the property
Parent (Root does not have Parent, obviously).

It makes me to know if it can interest.
-------------- next part --------------
' Gambas class file

' Module     : pgXml.class
' Author     : Luigi Carlotto
' Mail       : luigi.carlotto at ...120...
' Description: Xml object management.

INHERITS pgObject

CREATE PRIVATE 
-------------- next part --------------
' Gambas class file

' Module     : pgXmlAttribute.class
' Author     : Luigi Carlotto
' Mail       : luigi.carlotto at ...120...
' Description: Xml Attribute object management.

INHERITS pgXml

PROPERTY READ Parent AS pgXmlElement
PROPERTY Name AS String
PROPERTY Value AS String

PRIVATE $parent AS pgXmlElement
PRIVATE $name AS String 'name of attribute
PRIVATE $value AS String 'value of attribute

PUBLIC SUB _new(parent AS pgXmlElement, name AS String, OPTIONAL value AS String = "")
  $parent = parent
  $name = name
  $value = value
END

PRIVATE FUNCTION Parent_Read() AS pgXmlElement
  RETURN $parent
END

PRIVATE FUNCTION Name_Read() AS String
  RETURN $name
END
PRIVATE SUB Name_Write(Value AS String)
  $name = Value
END

PRIVATE FUNCTION Value_Read() AS String
  RETURN $value
END
PRIVATE SUB Value_Write(Value AS String)
  $value = Value
END
-------------- next part --------------
' Gambas class file

' Module     : pgXmlDocument.class
' Author     : Luigi Carlotto
' Mail       : luigi.carlotto at ...120...
' Description: Xml Document object management.

INHERITS pgXml

' Properties
PROPERTY READ Root AS pgXmlElement

PRIVATE $root AS pgXmlElement 'root

'---
' Constructor
'
PUBLIC SUB _new()
  $root = NEW pgXmlElement(NULL, "root")
END


PRIVATE FUNCTION Root_Read() AS pgXmlElement
  RETURN $root
END

'---
' Load data
'
' @parameter : String : Path
'
PUBLIC SUB Load(path AS String)
  DIM oRoot AS pgXmlElement
  DIM oElement AS pgXmlElement
  DIM oAttribute AS pgXmlAttribute
  DIM oXml AS NEW XmlReader
  $root.Name = "root"
  $root.Elements.Clear()
  $root.Attributes.Clear()
  oRoot = $root
  oXml.Open(path)
  DO UNTIL (oXml.Eof)
    SELECT CASE oXml.Node.Type
    CASE XmlReaderNodeType.Element
      oElement = NEW pgXmlElement(oRoot, oXml.Node.Name, oXml.Node.Value)
      FOR EACH oXml.Node.Attributes
        oAttribute = NEW pgXmlAttribute(oElement, oXml.Node.Name, oXml.Node.Value)
        oElement.Attributes.Add(oAttribute)
      NEXT
      oRoot.Elements.Add(oElement)
      oRoot = oElement
    CASE XmlReaderNodeType.EndElement
      oRoot = oRoot.Parent
    CASE XmlReaderNodeType.Text
      oElement.Value &= pgString.Trim(oXml.Node.Value)
    END SELECT 
    oXml.Read()
  LOOP
  oXml.Close()
END

PRIVATE SUB _loadElement(oXml AS XmlWriter, oRoot AS pgXmlElement)
END

'---
' Save data
'
' @parameter : String : Path
' @parameter : String : Indent
' @parameter : String : Encoding
'
PUBLIC SUB Save(path AS String, OPTIONAL indent AS Boolean = TRUE, OPTIONAL encoding AS String = "UTF8")
  DIM oXml AS NEW XmlWriter
  DIM oXmlElement AS pgXmlElement
  oXml.Open(path, indent, encoding)
  FOR EACH oXmlElement IN $root.Elements
    _saveElement(oXml, oXmlElement)
  NEXT 
  oXml.EndDocument()
END

PRIVATE SUB _saveElement(oXml AS XmlWriter, oRoot AS pgXmlElement)
  DIM oXmlElement AS pgXmlElement
  DIM oXmlAttribute AS pgXmlAttribute
  oXml.StartElement(oRoot.Name)
  IF (oRoot.Attributes.Count > 0) THEN 
    FOR EACH oXmlAttribute IN oRoot.Attributes
      oXml.Attribute(oXmlAttribute.Name, oXmlAttribute.Value)
    NEXT 
  END IF
  IF (oRoot.Elements.Count > 0) THEN 
    FOR EACH oXmlElement IN oRoot.Elements
      _saveElement(oXml, oXmlElement)
    NEXT 
  END IF
  oXml.Text(oRoot.Value)
  oXml.EndElement()
END

'---
' Print structure
'
' @parameter : String : Filename
'
PUBLIC SUB Print(filename AS String)
  DIM hFile AS File
  DIM oXmlElement AS pgXmlElement
  IF ($root.Elements.Count > 0) THEN 
    hFile = OPEN filename FOR OUTPUT CREATE
    FOR EACH oXmlElement IN $root.Elements
      _printElement(hFile, oXmlElement)
    NEXT 
    CLOSE #hFile
  END IF
END

PRIVATE SUB _printElement(hFile AS file, oRoot AS pgXmlElement, OPTIONAL level AS Integer = 0)
  DIM oElement AS pgXmlElement
  DIM oAttribute AS pgXmlAttribute
  IF (NOT pgTest.IsNull(oRoot)) THEN 
    PRINT #hFile, String(level, "  ") & "Start Element: " & oRoot.Name
    PRINT #hFile, String(level, "  ") & "  Value: \"" & oRoot.Value & "\""
    IF (oRoot.Attributes.Count > 0) THEN 
      FOR EACH oAttribute IN oRoot.Attributes
        PRINT #hFile, String(level, "  ") & "  Attribute:" & oAttribute.Name & " = \"" & oAttribute.Value & "\""
      NEXT 
    END IF
    IF (oRoot.Elements.Count > 0) THEN 
      FOR EACH oElement IN oRoot.Elements
        _printElement(hFile, oElement, level + 1)
      NEXT 
    END IF
    PRINT #hFile, String(level, "  ") & "End Element: " & oRoot.Name
  END IF
END
-------------- next part --------------
' Gambas class file

' Module     : pgXmlElement.class
' Author     : Luigi Carlotto
' Mail       : luigi.carlotto at ...120...
' Description: Xml Element object management.

INHERITS pgXml

PROPERTY READ Parent AS pgXmlElement
PROPERTY Name AS String
PROPERTY Value AS String
PROPERTY READ Attributes AS Object[]
PROPERTY READ Elements AS Object[]
PROPERTY Tag AS Boolean

PRIVATE $parent AS pgXmlElement
PRIVATE $name AS String 'name of element
PRIVATE $value AS String 'value of element
PRIVATE $attributes AS Object[] 'array of attributes
PRIVATE $elements AS Object[] 'array of elements
PRIVATE $tag AS Boolean

PUBLIC SUB _new(parent AS pgXmlElement, name AS String, OPTIONAL value AS String = "")
  $parent = parent
  $name = name
  $value = value
  $attributes = pgBase.NewObjectArray()
  $elements = pgBase.NewObjectArray()
END

PRIVATE FUNCTION Parent_Read() AS pgXmlElement
  RETURN $parent
END

PRIVATE FUNCTION Name_Read() AS String
  RETURN $name
END
PRIVATE SUB Name_Write(Value AS String)
  $name = Value
END

PRIVATE FUNCTION Value_Read() AS String
  RETURN $value
END
PRIVATE SUB Value_Write(Value AS String)
  $value = Value
END

PRIVATE FUNCTION Attributes_Read() AS Object[]
  RETURN $attributes
END

PRIVATE FUNCTION Elements_Read() AS Object[]
  RETURN $elements
END

PRIVATE FUNCTION Tag_Read() AS Boolean
  RETURN $tag
END
PRIVATE SUB Tag_Write(Value AS Boolean)
  $tag = Value
END

PUBLIC FUNCTION AddAttribute(name AS String, OPTIONAL value AS String = "") AS pgXmlAttribute
  DIM oXmlAttribute AS pgXmlAttribute
  oXmlAttribute = NEW pgXmlAttribute(ME, name, value)
  $attributes.Add(oXmlAttribute)
  RETURN oXmlAttribute
END

PUBLIC FUNCTION AddElement(name AS String, OPTIONAL value AS String = "") AS pgXmlElement
  DIM oXmlElement AS pgXmlElement
  oXmlElement = NEW pgXmlElement(ME, name, value)
  $elements.Add(oXmlElement)
  RETURN oXmlElement
END


More information about the User mailing list