(* Yaxi - Yet Another X* Implementation
 * Copyright (C) 2003 Matthieu Sozeau
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * 
 * $Id: yaxi_xslt.mli,v 1.16 2004/02/18 22:44:05 mat Exp $
 * 
 *)

 
(** Provides an XSLT implementation 
  The parser uses two passes:
  - parses the templates, params...
  - compile each template

*)

(** The XSL URI the transformer conforms to *)
val xsl_ns : Yaxi_xml.namespace

(** xmlns:xsl mapping (the prefix shouldn't be used), 
  it just help doing associative lists operations *)
val xsl_ns_mapping : Yaxi_xml.ns_mapping

(** Get a system's property, if the property doesn't exist,
  it returns default if it is set or raises Not_found *)
val get_property : ?default:Yaxi_xpath.primary_type ->
  Yaxi_xml.qname -> Yaxi_xpath.primary_type
  
(** Type of an xsl:test function *)
type xsl_test = Yaxi_xpath.global_context -> Yaxi_xpath.eval_context -> bool

type number_expr = Yaxi_xpath.global_context -> Yaxi_xpath.eval_context -> float

(** Attribute value templates *)
and value_template = [ `Expr of Yaxi_xpath.xpath_expr | `Text of string]

and uri_reference = string
and mode = string

(** Type of XSL patterns *)
and pattern = Yaxi_xpath.xpath_expr list

(** xsl:sort element *)
and xsl_sort = {
  select : Yaxi_xpath.xpath_expr;
  lang : Yaxi_xml.nmtoken;
  data_type: [`Text | `Number | `QName of string];
  order : [ `Ascending | `Descending];
  case_order : [ `Lower_first | `Upper_first];
} 
(** xsl:decimal-format element *)
and xsl_decimal_format = {
  name : Yaxi_xml.qname;
  decimal_separator : char;
  grouping_separator : char;
  infinity : string;
  minus_sign : char;
  nan : string;
  percent : char;
  per_mille : char;
  zero_digit : char;
  digit : char;
  pattern_separator : char;
} 
(** xsl:number element *)
and xsl_number = {
  level : [ `Any | `Multiple | `Single];
  count : pattern;
  from : pattern;
  value : number_expr;
  format : string;
  lang : Yaxi_xml.nmtoken;
  letter_value : [ `Alphabetic | `Traditional];
  grouping_separator : char;
  grouping_size : float;
} 
(** xsl:output element *)
and xsl_output = {
  method_: [`XML | `Text | `HTML | `QName of string ];
  version : Yaxi_xml.nmtoken;
  encoding : string;
  omit_xml_decl : bool;
  standalone : bool option;
  doctype_public : string;
  doctype_system : string;
  cdata_elements : Yaxi_xml.qnames;
  indent : bool;
  media_type : string;
} 

(** XSL control structures *)
and template =
    XSLIf of xsl_test * templates
  | XSLChoose of (xsl_test * templates) list * templates option
  | XSLValueOf of bool * Yaxi_xpath.xpath_expr
  | XSLCopy of Yaxi_xml.qname list * templates
  | XSLCopyOf of Yaxi_xpath.xpath_expr
  | XSLApplyTemplates of Yaxi_xpath.xpath_expr * mode * xsl_params * (xsl_sort list)
  | XSLCallTemplate of Yaxi_xml.qname * xsl_params
  | XSLApplyImports
  | XSLElement of Yaxi_xml.qname * templates
  | XSLOrigElement of Yaxi_xml.node ref * Yaxi_xml.qname * Yaxi_xml.nodeset ref *
      Yaxi_xml.nodeset ref * templates
  | XSLAttribute of Yaxi_xml.qname * templates
  | XSLText of bool * Yaxi_xml.cdata
  | XSLFallback of templates
  | XSLForEach of Yaxi_xpath.xpath_expr * templates * (xsl_sort list)
  | XSLMessage of bool * templates
  | XSLProcessingInstruction of Yaxi_xml.ncname * templates
  | XSLVariable of xsl_param
  | XSLParam of xsl_param
  | XSLExtension of instruction
  | XSLNop
and templates = template list

(** XSL parameter/variable *)
and xsl_param = 
    Yaxi_xml.qname                  (** name *)
    * Yaxi_xpath.xpath_expr option  (** select expression *)
    * templates option         (** Content template *)
and xsl_params = xsl_param list
and xsl_key = Yaxi_xml.qname * (Yaxi_xpath.xpath_expr * Yaxi_xpath.xpath_expr)

(** xsl:template element *)
and xsl_template = {
  match_expr : (float * Yaxi_xpath.xpath_expr) list;   (** Match string, priority, match expr *)
  name : Yaxi_xml.qname option;                                 (** name *)
  parameters : xsl_params;                                      (** Parameters list *)
  instructions : templates ref;                                 (** Content templates *)
  mutable compiled_fun : (Yaxi_xpath.global_context -> Yaxi_xpath.eval_context -> Yaxi_xml.nodeset option) option;   (** Compiled function *)
} 

(** Stylesheet *)
and stylesheet = {
  mutable templates : xsl_template list;
  mutable params : xsl_param list;
  mutable variables : xsl_param list;

  mutable namespaces: Yaxi_xml.ns_mapping list; (** The namespaces used in the stylesheet (declared on the stylesheed document element) *)
  mutable namespace_aliases : (string * string) list;

  mutable attribute_sets : (Yaxi_xml.qname * (Yaxi_xml.qname * templates) list) list;
  mutable decimal_formats : xsl_decimal_format list;
  mutable preserve_space : Yaxi_xpath.xpath_expr list;
  mutable strip_space : Yaxi_xpath.xpath_expr list;
  mutable imports : (uri_reference * stylesheet) list;

  mutable keys : xsl_key list;
  mutable output: xsl_output option;

  mutable extension_prefixes: Yaxi_xml.ncname list;
  mutable extension_elements: extension_elements list;
  mutable extension_functions: extension_functions list;
} 

and instruction = Yaxi_xpath.global_context -> 
  Yaxi_xpath.eval_context -> 
  Yaxi_xml.nodeset option
  
and xslt_extension_element = 
  Yaxi_xml.node -> stylesheet -> 
  Yaxi_xml.ns_mappings -> 
  Yaxi_xml.ncnames -> instruction

and extension_element = Yaxi_xml.ncname * xslt_extension_element
and extension_elements = string * extension_element list

and xslt_extension_function = stylesheet -> Yaxi_xml.document -> Yaxi_xpath.xpath_function
and extension_function = Yaxi_xml.ncname * xslt_extension_function
and extension_functions = string * extension_function list

(** Exception launched when the stylesheet does not conform to the spec *)
exception XSLError of string

(** Exception launched when an halting message is encountered *)
exception XSLStylesheetDirectedStop

(** Evaluates an XPath expression with the xsl prefix bound to the XSLT namespace *)
val xpath_eval : string -> Yaxi_xml.node -> Yaxi_xpath.primary_type

(** Transform the xpath steps of a pattern using the rules of XSL. *)
val transform_steps :
  ?first_axis:Yaxi_xpath.axis ->
  Yaxi_xpath.steps -> Yaxi_xpath.steps

(** Parse an XSL pattern *)
val parse_pattern : ?first_axis:Yaxi_xpath.axis -> string -> Yaxi_xpath.expression list

(** Compile an XSL pattern *)
val compile_pattern : ?first_axis:Yaxi_xpath.axis -> string -> Yaxi_xpath.xpath_expr
  
(** String representation of a template *)
val string_of_template : xsl_template -> string
  
(** String representation of a parameter *)
val string_of_param : xsl_param -> string

(** Parses some stylesheet instruction *)
val parse_instruction : stylesheet -> Yaxi_xml.ns_mappings ->
  Yaxi_xml.ncnames -> Yaxi_xml.node -> template

(** Parses some stylesheet instructions *)
val parse_instructions : stylesheet -> Yaxi_xml.ns_mappings ->
  Yaxi_xml.ncnames -> Yaxi_xml.nodeset -> template list
  
(** Parses a stylesheet document *)
val parse_stylesheet : ?extension_elements:(extension_elements list) -> 
  ?extension_functions:(extension_functions list) ->
  Yaxi_xml.document -> stylesheet
  
(** Parse a stylesheet file *)
val parse_stylesheet_file : ?extension_elements:(extension_elements list) -> 
  ?extension_functions:(extension_functions list) ->
  string -> stylesheet

(** Compiles an template of text and \{ \} enclosed XPath expressions into an xpath
  expression resulting in the aggregation of text and evaluated xpath expression nodes.
  An attribute template result is the 'string value' of this function's result.
  @param attr The template string containing xpath expressions inside curly braces.
*)
val compile_curly_template : string -> Yaxi_xpath.global_context -> Yaxi_xpath.eval_context
  -> Yaxi_xml.nodeset

(** Compiles an attribute template 
  @param attribute The attribute template string containing xpath expressions inside curly braces.
*)
val compile_attribute_template : Yaxi_xml.attribute_value -> 
  Yaxi_xpath.global_context -> Yaxi_xpath.eval_context -> Yaxi_xml.attribute_value

(** Compiles the function associated with some template instrustions *)
val compile_templates : stylesheet -> template list -> instruction list

(** Compiles the function associated with a template *)
val compile_template : stylesheet -> xsl_template -> unit

(** Compile all the stylesheet templates *)
val compile_stylesheet : stylesheet -> unit

(** Get the compiled function for a template *)
val get_template_fun :
  stylesheet -> xsl_template -> Yaxi_xpath.global_context -> Yaxi_xpath.eval_context -> Yaxi_xml.nodeset option

(** Apply the given templates in order to the context
  @return the resulting document fragments
*)
val apply_templates : instruction list -> Yaxi_xpath.global_context ->
  Yaxi_xpath.eval_context -> Yaxi_xml.nodeset

(** Used internaly to add XSLT XPath extension functions (document, key...) 
  Not to be used by extension elements with a namespace!
*)
val add_additional_functions : extension_function list -> unit

(** Apply a stylesheet to a document.
  @param parameters A list a parameters to use.
  @return the result document 
*)
val apply_stylesheet :
  stylesheet:stylesheet ->
  document:Yaxi_xml.document ->
  ?ns_mappings:Yaxi_xml.ns_mappings ->
  ?parameters:(Yaxi_xml.qname * Yaxi_xpath.xpath_expr) list ->
  ?extension_functions:(extension_functions list) ->
  unit -> Yaxi_xml.document
  
