Simple API for XML

Matreshka provides SAX-style reader and writer for XML 1.0/1.1. Corresponding Namespaces in XML specifications are supported also.

Matreshka's SAX reader can use Ada streams, strings, files and sockets as input source. It supports incremental parsing of streams (when control returns to the caller after processing of the portion of stream). It approximately 30% faster then XmlAda's reader and has the same performance as Qt's reader.

API uses Universal_String to represent all text data which hides complexity of encoding handling from application. SAX event handlers has additional 'in out' parameter to control future processing of the document/stream and additional subprogram Error_String to report application errors in centralized manner. This provides more control over document/stream processing, improves application's code readability, and helps to develop localized applications. Reporting of application level errors by exceptions mechanism is also supported.

SAX writer allows to generate XML documents and streams from the application. It supports strings as output destination now. It supports incremental generation of XML streams also.

Packages Overview

SAX API contains many Ada packages, but not all of them intended to be used by applications. Here is list of packages which application can use:

Package Description
XML.SAX.Attributes Provides set of XML attributes
XML.SAX.Content_Handlers Provides interface type to handle content of the document
XML.SAX.Declaration_Handlers Provides interface type to handle some declarations in the document which XML processor must report to application
XML.SAX.Default_Handlers Provides "default" implementation of all handles, all subprogram do nothing
XML.SAX.DTD_Handlers Provides interface type to handle additional declarations if the document
XML.SAX.Entity_Resolvers Provides interface type to resolve external entities
XML.SAX.Error_Handlers Provides interface type to handle errors in document
XML.SAX.Input_Sources Provides interface type of input source
XML.SAX.Input_Sources.Streams Provides implementation of input source to read data from the Ada stream
XML.SAX.Input_Sources.Streams.Files Provides implementation of input source to read data from files
XML.SAX.Input_Sources.Streams.Sockets Provides implementation of input source to read data from network socket
XML.SAX.Input_Sources.Strings Provides implementation to process data represented as Universal_String
XML.SAX.Lexical_Handlers Provides interface type to handle some lexical elements in th document
XML.SAX.Locators Provides implementation of the object to retrieve position of current item in the document
XML.SAX.Output_Destinations Not implemented yet
XML.SAX.Parse_Exceptions Provides implementation of object to represent errors in the document
XML.SAX.Pretty_Writers Provides implementation of SAX writer to output XML
XML.SAX.Readers Provides interface type of SAX reader
XML.SAX.Simple_Readers Provides simple implementation SAX reader. It supports namespaces and partially supports validation
XML.SAX.Writers Provides interface type for SAX writers and set of convenience subprograms

Other packages are part of the implementation and must not be used by the application.


SAX Reader Example

Example of use of SAX Reader is present in examples/sax_event_printer directory. This program reads XML document from the specified file and outputs SAX events from all handlers.

with Ada.Command_Line;

with League.Strings;
with XML.SAX.Input_Sources.Streams.Files;
with XML.SAX.Simple_Readers;

with Events_Printers;

procedure Sax_Events_Printer is
   Source  : aliased XML.SAX.Input_Sources.Streams.Files.File_Input_Source;
   Reader  : aliased XML.SAX.Simple_Readers.SAX_Simple_Reader;
   Handler : aliased Events_Printers.Events_Printer;

   XML.SAX.Simple_Readers.Put_Line := Put_Line'Access;
   Reader.Set_Content_Handler (Handler'Unchecked_Access);
   Reader.Set_Declaration_Handler (Handler'Unchecked_Access);
   Reader.Set_DTD_Handler (Handler'Unchecked_Access);
   Reader.Set_Entity_Resolver (Handler'Unchecked_Access);
   Reader.Set_Error_Handler (Handler'Unchecked_Access);
   Reader.Set_Lexical_Handler (Handler'Unchecked_Access);

   Source.Open (Ada.Command_Line.Argument (1));
   Reader.Parse (Source'Access);
end Sax_Events_Printer;

To build application:

  1. Enter examples/sax_events_printer directory.
  2. Run gprbuild to build demo program.

To play with demo program run

./sax_events_printer <file.xml>

SAX Writer Example

SAX writer allows to generate XML documents and streams. Below is small example of its use to generate XMPP stream.

--  This is example of usage of XML Writer to generate XML files from
--  application. It generates initial part of XMPP stream.
with Ada.Wide_Wide_Text_IO;

with League.Strings;
with XML.SAX.Attributes;
with XML.SAX.Pretty_Writers;

procedure SAX_Writer is

   use League.Strings;

   function "+" (Item : Wide_Wide_String) return Universal_String
     renames To_Universal_String;

   XML_URI             : constant Universal_String
     := +"";
   Lang_Attribute      : constant Universal_String := +"lang";
   Stream_URI          : constant Universal_String
     := +"";
   Stream_Prefix       : constant Universal_String := +"stream";
   Stream_Element      : constant Universal_String := +"stream";
   Features_Element    : constant Universal_String := +"features";
   Client_URI          : constant Universal_String := +"jabber:client";
   Id_Attribute        : constant Universal_String := +"id";
   From_Attribute      : constant Universal_String := +"from";
   Version_Attribute   : constant Universal_String := +"version";
   Compression_URI     : constant Universal_String
     := +"";
   Compression_Element : constant Universal_String := +"compression";
   Method_Element      : constant Universal_String := +"method";

   Writer     : XML.SAX.Pretty_Writers.SAX_Pretty_Writer;
   Attributes : XML.SAX.Attributes.SAX_Attributes;

   Writer.Start_Prefix_Mapping (Namespace_URI => Client_URI);
     (Namespace_URI => Stream_URI, Prefix => Stream_Prefix);

   --  Open stream element

     (Qualified_Name => Id_Attribute, Value => +"656571601");
     (Qualified_Name => From_Attribute, Value => +"");
   Attributes.Set_Value (Qualified_Name => Version_Attribute, Value => +"1.0");
     (Namespace_URI => XML_URI, Local_Name => Lang_Attribute, Value => +"ru");
     (Namespace_URI => Stream_URI,
      Local_Name    => Stream_Element,
      Attributes    => Attributes);

   --  Open features element

     (Namespace_URI => Stream_URI, Local_Name => Features_Element);

   --  Open compression element

   Writer.Start_Prefix_Mapping (Namespace_URI => Compression_URI);
     (Namespace_URI => Compression_URI, Local_Name => Compression_Element);

   --  Output method

     (Namespace_URI => Compression_URI, Local_Name => Method_Element);
   Writer.Characters (+"zlib");
     (Namespace_URI => Compression_URI, Local_Name => Method_Element);

   --  Close compression element

     (Namespace_URI => Compression_URI, Local_Name => Compression_Element);

   --  Close features element

     (Namespace_URI => Stream_URI, Local_Name => Features_Element);

   --  Close stream element

     (Namespace_URI => Stream_URI, Local_Name => Stream_Element);
   Writer.End_Prefix_Mapping (Prefix => Stream_Prefix);

   Ada.Wide_Wide_Text_IO.Put_Line (Writer.Text.To_Wide_Wide_String);
end SAX_Writer;

This program generates following output (output is formatted to be more readable):

<?xml version="1.0"?>
<stream:stream xmlns="jabber:client" xmlns:stream=""
  id="656571601" from="" version="1.0" xml:lang="ru">
    <compression xmlns="">
Last modified 6 years ago Last modified on Apr 4, 2011, 11:25:51 PM