]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/DEVEL/pxp/pxp/doc/manual/html/x550.html
Initial revision
[helm.git] / helm / DEVEL / pxp / pxp / doc / manual / html / x550.html
diff --git a/helm/DEVEL/pxp/pxp/doc/manual/html/x550.html b/helm/DEVEL/pxp/pxp/doc/manual/html/x550.html
new file mode 100644 (file)
index 0000000..f2dcdd7
--- /dev/null
@@ -0,0 +1,765 @@
+<HTML
+><HEAD
+><TITLE
+>How to parse a document from an application</TITLE
+><META
+NAME="GENERATOR"
+CONTENT="Modular DocBook HTML Stylesheet Version 1.46"><LINK
+REL="HOME"
+TITLE="The PXP user's guide"
+HREF="index.html"><LINK
+REL="UP"
+TITLE="Using PXP"
+HREF="c533.html"><LINK
+REL="PREVIOUS"
+TITLE="Using PXP"
+HREF="c533.html"><LINK
+REL="NEXT"
+TITLE="Class-based processing of the node tree"
+HREF="x675.html"><LINK
+REL="STYLESHEET"
+TYPE="text/css"
+HREF="markup.css"></HEAD
+><BODY
+CLASS="SECT1"
+BGCOLOR="#FFFFFF"
+TEXT="#000000"
+LINK="#0000FF"
+VLINK="#840084"
+ALINK="#0000FF"
+><DIV
+CLASS="NAVHEADER"
+><TABLE
+WIDTH="100%"
+BORDER="0"
+CELLPADDING="0"
+CELLSPACING="0"
+><TR
+><TH
+COLSPAN="3"
+ALIGN="center"
+>The PXP user's guide</TH
+></TR
+><TR
+><TD
+WIDTH="10%"
+ALIGN="left"
+VALIGN="bottom"
+><A
+HREF="c533.html"
+>Prev</A
+></TD
+><TD
+WIDTH="80%"
+ALIGN="center"
+VALIGN="bottom"
+>Chapter 2. Using <SPAN
+CLASS="ACRONYM"
+>PXP</SPAN
+></TD
+><TD
+WIDTH="10%"
+ALIGN="right"
+VALIGN="bottom"
+><A
+HREF="x675.html"
+>Next</A
+></TD
+></TR
+></TABLE
+><HR
+ALIGN="LEFT"
+WIDTH="100%"></DIV
+><DIV
+CLASS="SECT1"
+><H1
+CLASS="SECT1"
+><A
+NAME="AEN550"
+>2.2. How to parse a document from an application</A
+></H1
+><P
+>Let me first give a rough overview of the object model of the parser. The
+following items are represented by objects:
+
+<P
+></P
+><UL
+COMPACT="COMPACT"
+><LI
+STYLE="list-style-type: disc"
+><P
+><I
+CLASS="EMPHASIS"
+>Documents:</I
+> The document representation is more or less the
+anchor for the application; all accesses to the parsed entities start here. It
+is described by the class <TT
+CLASS="LITERAL"
+>document</TT
+> contained in the module
+<TT
+CLASS="LITERAL"
+>Pxp_document</TT
+>. You can get some global information, such
+as the XML declaration the document begins with, the DTD of the document,
+global processing instructions, and most important, the document tree. </P
+></LI
+><LI
+STYLE="list-style-type: disc"
+><P
+><I
+CLASS="EMPHASIS"
+>The contents of documents:</I
+> The contents have the structure
+of a tree: Elements contain other elements and text<A
+NAME="AEN562"
+HREF="#FTN.AEN562"
+>[1]</A
+>. 
+
+The common type to represent both kinds of content is <TT
+CLASS="LITERAL"
+>node</TT
+>
+which is a class type that unifies the properties of elements and character
+data. Every node has a list of children (which is empty if the element is empty
+or the node represents text); nodes may have attributes; nodes have always text
+contents. There are two implementations of <TT
+CLASS="LITERAL"
+>node</TT
+>, the class
+<TT
+CLASS="LITERAL"
+>element_impl</TT
+> for elements, and the class
+<TT
+CLASS="LITERAL"
+>data_impl</TT
+> for text data. You find these classes and class
+types in the module <TT
+CLASS="LITERAL"
+>Pxp_document</TT
+>, too.</P
+><P
+>Note that attribute lists are represented by non-class values.</P
+></LI
+><LI
+STYLE="list-style-type: disc"
+><P
+><I
+CLASS="EMPHASIS"
+>The node extension:</I
+> For advanced usage, every node of the
+document may have an associated <I
+CLASS="EMPHASIS"
+>extension</I
+> which is simply
+a second object. This object must have the three methods
+<TT
+CLASS="LITERAL"
+>clone</TT
+>, <TT
+CLASS="LITERAL"
+>node</TT
+>, and
+<TT
+CLASS="LITERAL"
+>set_node</TT
+> as bare minimum, but you are free to add methods as
+you want. This is the preferred way to add functionality to the document
+tree<A
+NAME="AEN582"
+HREF="#FTN.AEN582"
+>[2]</A
+>. The class type <TT
+CLASS="LITERAL"
+>extension</TT
+> is
+defined in <TT
+CLASS="LITERAL"
+>Pxp_document</TT
+>, too.</P
+></LI
+><LI
+STYLE="list-style-type: disc"
+><P
+><I
+CLASS="EMPHASIS"
+>The DTD:</I
+> Sometimes it is necessary to access the DTD of a
+document; the average application does not need this feature. The class
+<TT
+CLASS="LITERAL"
+>dtd</TT
+> describes DTDs, and makes it possible to get
+representations of element, entity, and notation declarations as well as
+processing instructions contained in the DTD. This class, and
+<TT
+CLASS="LITERAL"
+>dtd_element</TT
+>, <TT
+CLASS="LITERAL"
+>dtd_notation</TT
+>, and
+<TT
+CLASS="LITERAL"
+>proc_instruction</TT
+> can be found in the module
+<TT
+CLASS="LITERAL"
+>Pxp_dtd</TT
+>. There are a couple of classes representing
+different kinds of entities; these can be found in the module
+<TT
+CLASS="LITERAL"
+>Pxp_entity</TT
+>. </P
+></LI
+></UL
+>
+
+Additionally, the following modules play a role:
+
+<P
+></P
+><UL
+COMPACT="COMPACT"
+><LI
+STYLE="list-style-type: disc"
+><P
+><I
+CLASS="EMPHASIS"
+>Pxp_yacc:</I
+> Here the main parsing functions such as
+<TT
+CLASS="LITERAL"
+>parse_document_entity</TT
+> are located. Some additional types and
+functions allow the parser to be configured in a non-standard way.</P
+></LI
+><LI
+STYLE="list-style-type: disc"
+><P
+><I
+CLASS="EMPHASIS"
+>Pxp_types:</I
+> This is a collection of basic types and
+exceptions. </P
+></LI
+></UL
+>
+
+There are some further modules that are needed internally but are not part of
+the API.</P
+><P
+>Let the document to be parsed be stored in a file called
+<TT
+CLASS="LITERAL"
+>doc.xml</TT
+>. The parsing process is started by calling the
+function
+
+<PRE
+CLASS="PROGRAMLISTING"
+>val parse_document_entity : config -&#62; source -&#62; 'ext spec -&#62; 'ext document</PRE
+>
+
+defined in the module <TT
+CLASS="LITERAL"
+>Pxp_yacc</TT
+>. The first argument
+specifies some global properties of the parser; it is recommended to start with
+the <TT
+CLASS="LITERAL"
+>default_config</TT
+>. The second argument determines where the
+document to be parsed comes from; this may be a file, a channel, or an entity
+ID. To parse <TT
+CLASS="LITERAL"
+>doc.xml</TT
+>, it is sufficient to pass
+<TT
+CLASS="LITERAL"
+>from_file "doc.xml"</TT
+>. </P
+><P
+>The third argument passes the object specification to use. Roughly
+speaking, it determines which classes implement the node objects of which
+element types, and which extensions are to be used. The <TT
+CLASS="LITERAL"
+>'ext</TT
+>
+polymorphic variable is the type of the extension. For the moment, let us
+simply pass <TT
+CLASS="LITERAL"
+>default_spec</TT
+> as this argument, and ignore it.</P
+><P
+>So the following expression parses <TT
+CLASS="LITERAL"
+>doc.xml</TT
+>:
+
+<PRE
+CLASS="PROGRAMLISTING"
+>open Pxp_yacc
+let d = parse_document_entity default_config (from_file "doc.xml") default_spec</PRE
+>
+
+Note that <TT
+CLASS="LITERAL"
+>default_config</TT
+> implies that warnings are collected
+but not printed. Errors raise one of the exception defined in
+<TT
+CLASS="LITERAL"
+>Pxp_types</TT
+>; to get readable errors and warnings catch the
+exceptions as follows:
+
+<PRE
+CLASS="PROGRAMLISTING"
+>class warner =
+  object 
+    method warn w =
+      print_endline ("WARNING: " ^ w)
+  end
+;;
+
+try
+  let config = { default_config with warner = new warner } in
+  let d = parse_document_entity config (from_file "doc.xml") default_spec
+  in
+    ...
+with
+   e -&#62;
+     print_endline (Pxp_types.string_of_exn e)</PRE
+>
+
+Now <TT
+CLASS="LITERAL"
+>d</TT
+> is an object of the <TT
+CLASS="LITERAL"
+>document</TT
+>
+class. If you want the node tree, you can get the root element by
+
+<PRE
+CLASS="PROGRAMLISTING"
+>let root = d # root</PRE
+>
+
+and if you would rather like to access the DTD, determine it by
+
+<PRE
+CLASS="PROGRAMLISTING"
+>let dtd = d # dtd</PRE
+>
+
+As it is more interesting, let us investigate the node tree now. Given the root
+element, it is possible to recursively traverse the whole tree. The children of
+a node <TT
+CLASS="LITERAL"
+>n</TT
+> are returned by the method
+<TT
+CLASS="LITERAL"
+>sub_nodes</TT
+>, and the type of a node is returned by
+<TT
+CLASS="LITERAL"
+>node_type</TT
+>. This function traverses the tree, and prints the
+type of each node:
+
+<PRE
+CLASS="PROGRAMLISTING"
+>let rec print_structure n =
+  let ntype = n # node_type in
+  match ntype with
+    T_element name -&#62;
+      print_endline ("Element of type " ^ name);
+      let children = n # sub_nodes in
+      List.iter print_structure children
+  | T_data -&#62;
+      print_endline "Data"
+  | _ -&#62;
+      (* Other node types are not possible unless the parser is configured
+         differently.
+       *)
+      assert false</PRE
+>
+
+You can call this function by
+
+<PRE
+CLASS="PROGRAMLISTING"
+>print_structure root</PRE
+>
+
+The type returned by <TT
+CLASS="LITERAL"
+>node_type</TT
+> is either <TT
+CLASS="LITERAL"
+>T_element
+name</TT
+> or <TT
+CLASS="LITERAL"
+>T_data</TT
+>. The <TT
+CLASS="LITERAL"
+>name</TT
+> of the
+element type is the string included in the angle brackets. Note that only
+elements have children; data nodes are always leaves of the tree.</P
+><P
+>There are some more methods in order to access a parsed node tree:
+
+<P
+></P
+><UL
+COMPACT="COMPACT"
+><LI
+STYLE="list-style-type: disc"
+><P
+><TT
+CLASS="LITERAL"
+>n # parent</TT
+>: Returns the parent node, or raises
+<TT
+CLASS="LITERAL"
+>Not_found</TT
+> if the node is already the root</P
+></LI
+><LI
+STYLE="list-style-type: disc"
+><P
+><TT
+CLASS="LITERAL"
+>n # root</TT
+>: Returns the root of the node tree. </P
+></LI
+><LI
+STYLE="list-style-type: disc"
+><P
+><TT
+CLASS="LITERAL"
+>n # attribute a</TT
+>: Returns the value of the attribute with
+name <TT
+CLASS="LITERAL"
+>a</TT
+>. The method returns a value for every
+<I
+CLASS="EMPHASIS"
+>declared</I
+> attribute, independently of whether the attribute
+instance is defined or not. If the attribute is not declared,
+<TT
+CLASS="LITERAL"
+>Not_found</TT
+> will be raised. (In well-formedness mode, every
+attribute is considered as being implicitly declared with type
+<TT
+CLASS="LITERAL"
+>CDATA</TT
+>.) </P
+><P
+>The following return values are possible: <TT
+CLASS="LITERAL"
+>Value s</TT
+>, 
+<TT
+CLASS="LITERAL"
+>Valuelist sl</TT
+> , and <TT
+CLASS="LITERAL"
+>Implied_value</TT
+>. 
+The first two value types indicate that the attribute value is available,
+either because there is a definition
+<TT
+CLASS="LITERAL"
+><TT
+CLASS="REPLACEABLE"
+><I
+>a</I
+></TT
+>="<TT
+CLASS="REPLACEABLE"
+><I
+>value</I
+></TT
+>"</TT
+>
+in the XML text, or because there is a default value (declared in the
+DTD). Only if both the instance definition and the default declaration are
+missing, the latter value <TT
+CLASS="LITERAL"
+>Implied_value</TT
+> will be returned.</P
+><P
+>In the DTD, every attribute is typed. There are single-value types (CDATA, ID,
+IDREF, ENTITY, NMTOKEN, enumerations), in which case the method passes
+<TT
+CLASS="LITERAL"
+>Value s</TT
+> back, where <TT
+CLASS="LITERAL"
+>s</TT
+> is the normalized
+string value of the attribute. The other types (IDREFS, ENTITIES, NMTOKENS)
+represent list values, and the parser splits the XML literal into several
+tokens and returns these tokens as <TT
+CLASS="LITERAL"
+>Valuelist sl</TT
+>.</P
+><P
+>Normalization means that entity references (the
+<TT
+CLASS="LITERAL"
+>&amp;<TT
+CLASS="REPLACEABLE"
+><I
+>name</I
+></TT
+>;</TT
+> tokens) and
+character references
+(<TT
+CLASS="LITERAL"
+>&amp;#<TT
+CLASS="REPLACEABLE"
+><I
+>number</I
+></TT
+>;</TT
+>) are replaced
+by the text they represent, and that white space characters are converted into
+plain spaces.</P
+></LI
+><LI
+STYLE="list-style-type: disc"
+><P
+><TT
+CLASS="LITERAL"
+>n # data</TT
+>: Returns the character data contained in the
+node. For data nodes, the meaning is obvious as this is the main content of
+data nodes. For element nodes, this method returns the concatenated contents of
+all inner data nodes.</P
+><P
+>Note that entity references included in the text are resolved while they are
+being parsed; for example the text "a &#38;lt;&#38;gt; b" will be returned
+as "a &#60;&#62; b" by this method. Spaces of data nodes are always
+preserved. Newlines are preserved, but always converted to \n characters even
+if newlines are encoded as \r\n or \r. Normally you will never see two adjacent
+data nodes because the parser collapses all data material at one location into
+one node. (However, if you create your own tree or transform the parsed tree,
+it is possible to have adjacent data nodes.)</P
+><P
+>Note that elements that do <I
+CLASS="EMPHASIS"
+>not</I
+> allow #PCDATA as content
+will not have data nodes as children. This means that spaces and newlines, the
+only character material allowed for such elements, are silently dropped.</P
+></LI
+></UL
+>
+
+For example, if the task is to print all contents of elements with type
+"valuable" whose attribute "priority" is "1", this function can help:
+
+<PRE
+CLASS="PROGRAMLISTING"
+>let rec print_valuable_prio1 n =
+  let ntype = n # node_type in
+  match ntype with
+    T_element "valuable" when n # attribute "priority" = Value "1" -&#62;
+      print_endline "Valuable node with priotity 1 found:";
+      print_endline (n # data)
+  | (T_element _ | T_data) -&#62;
+      let children = n # sub_nodes in
+      List.iter print_valuable_prio1 children
+  | _ -&#62;
+      assert false</PRE
+>
+
+You can call this function by:
+
+<PRE
+CLASS="PROGRAMLISTING"
+>print_valuable_prio1 root</PRE
+>
+
+If you like a DSSSL-like style, you can make the function
+<TT
+CLASS="LITERAL"
+>process_children</TT
+> explicit:
+
+<PRE
+CLASS="PROGRAMLISTING"
+>let rec print_valuable_prio1 n =
+
+  let process_children n =
+    let children = n # sub_nodes in
+    List.iter print_valuable_prio1 children 
+  in
+
+  let ntype = n # node_type in
+  match ntype with
+    T_element "valuable" when n # attribute "priority" = Value "1" -&#62;
+      print_endline "Valuable node with priority 1 found:";
+      print_endline (n # data)
+  | (T_element _ | T_data) -&#62;
+      process_children n
+  | _ -&#62;
+      assert false</PRE
+>
+
+So far, O'Caml is now a simple "style-sheet language": You can form a big
+"match" expression to distinguish between all significant cases, and provide
+different reactions on different conditions. But this technique has
+limitations; the "match" expression tends to get larger and larger, and it is
+difficult to store intermediate values as there is only one big
+recursion. Alternatively, it is also possible to represent the various cases as
+classes, and to use dynamic method lookup to find the appropiate class. The
+next section explains this technique in detail.&#13;</P
+></DIV
+><H3
+CLASS="FOOTNOTES"
+>Notes</H3
+><TABLE
+BORDER="0"
+CLASS="FOOTNOTES"
+WIDTH="100%"
+><TR
+><TD
+ALIGN="LEFT"
+VALIGN="TOP"
+WIDTH="5%"
+><A
+NAME="FTN.AEN562"
+HREF="x550.html#AEN562"
+>[1]</A
+></TD
+><TD
+ALIGN="LEFT"
+VALIGN="TOP"
+WIDTH="95%"
+><P
+>Elements may
+also contain processing instructions. Unlike other document models, <SPAN
+CLASS="ACRONYM"
+>PXP</SPAN
+>
+separates processing instructions from the rest of the text and provides a
+second interface to access them (method <TT
+CLASS="LITERAL"
+>pinstr</TT
+>). However,
+there is a parser option (<TT
+CLASS="LITERAL"
+>enable_pinstr_nodes</TT
+>) which changes
+the behaviour of the parser such that extra nodes for processing instructions
+are included into the tree.</P
+><P
+>Furthermore, the tree does normally not contain nodes for XML comments;
+they are ignored by default. Again, there is an option
+(<TT
+CLASS="LITERAL"
+>enable_comment_nodes</TT
+>) changing this.</P
+></TD
+></TR
+><TR
+><TD
+ALIGN="LEFT"
+VALIGN="TOP"
+WIDTH="5%"
+><A
+NAME="FTN.AEN582"
+HREF="x550.html#AEN582"
+>[2]</A
+></TD
+><TD
+ALIGN="LEFT"
+VALIGN="TOP"
+WIDTH="95%"
+><P
+>Due to the typing system it is more or less impossible to
+derive recursive classes in O'Caml. To get around this, it is common practice
+to put the modifiable or extensible part of recursive objects into parallel
+objects.</P
+></TD
+></TR
+></TABLE
+><DIV
+CLASS="NAVFOOTER"
+><HR
+ALIGN="LEFT"
+WIDTH="100%"><TABLE
+WIDTH="100%"
+BORDER="0"
+CELLPADDING="0"
+CELLSPACING="0"
+><TR
+><TD
+WIDTH="33%"
+ALIGN="left"
+VALIGN="top"
+><A
+HREF="c533.html"
+>Prev</A
+></TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="index.html"
+>Home</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+><A
+HREF="x675.html"
+>Next</A
+></TD
+></TR
+><TR
+><TD
+WIDTH="33%"
+ALIGN="left"
+VALIGN="top"
+>Using <SPAN
+CLASS="ACRONYM"
+>PXP</SPAN
+></TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="c533.html"
+>Up</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+>Class-based processing of the node tree</TD
+></TR
+></TABLE
+></DIV
+></BODY
+></HTML
+>
\ No newline at end of file