diff --git a/metadata/entries/XML.toml b/metadata/entries/XML.toml
--- a/metadata/entries/XML.toml
+++ b/metadata/entries/XML.toml
@@ -1,36 +1,41 @@
title = "XML"
date = 2014-10-03
topics = [
"Computer science/Functional programming",
"Computer science/Data structures",
]
abstract = """
This entry provides an XML library for Isabelle/HOL. This includes parsing
and pretty printing of XML trees as well as combinators for transforming XML
trees into arbitrary user-defined data. The main contribution of this entry is
an interface (fit for code generation) that allows for communication between
verified programs formalized in Isabelle/HOL and the outside world via XML.
This library was developed as part of the IsaFoR/CeTA project
to which we refer for examples of its usage."""
license = "bsd"
note = ""
[authors]
[authors.sternagel]
email = "sternagel_email"
[authors.thiemann]
email = "thiemann_email"
+[authors.yamada]
+email = "yamada_email"
+
[contributors]
[notify]
sternagel = "sternagel_email"
thiemann = "thiemann_email"
+yamada = "yamada_email"
[history]
+2024-04-12 = "Switched to new XML-transformers, developed by Akihisa Yamada. "
[extra]
[related]
diff --git a/thys/XML/Example_Application.thy b/thys/XML/Example_Application.thy
new file mode 100644
--- /dev/null
+++ b/thys/XML/Example_Application.thy
@@ -0,0 +1,51 @@
+(*
+Author: René Thiemann
+*)
+theory Example_Application
+ imports
+ Xmlt
+begin
+
+text \Let us consider inputs that consist of an optional number and a list of first order terms,
+ where these terms use strings as function names and numbers for variables.
+ We assume that we have a XML-document that describes these kinds of inputs and now want to parse them.\
+
+definition exampleInput where "exampleInput = STR
+ ''
+ 42
+
+ fo<>bar
+ 1
+ 3
+
+ 15
+ ''"
+
+datatype fo_term = Fun string "fo_term list" | Var int
+
+definition var :: "fo_term xmlt" where "var = xml_change (xml_int (STR ''var'')) (xml_return \ Var)"
+
+text \a recursive parser is best defined via partial-function. Note that the xml-argument
+ should be provided, otherwise strict evalution languages will not terminate.\
+partial_function (sum_bot) parse_term :: "fo_term xmlt"
+where
+ [code]: "parse_term xml = (
+ XMLdo (STR ''funapp'') {
+ name \ xml_text (STR ''symbol'');
+ args \* parse_term;
+ xml_return (Fun name args)
+ } XMLor var) xml"
+
+text \for non-recursive parsers, we can eta-contract\
+definition parse_input :: "(int option \ fo_term list) xmlt" where
+ "parse_input = XMLdo (STR ''input'') {
+ onum \? xml_int (STR ''magicNumber'');
+ terms \* parse_term;
+ xml_return (onum,terms)
+ }"
+
+definition test where "test = parse_xml_string parse_input (String.explode exampleInput)"
+
+value test (* successfully parses the example input *)
+export_code test checking SML
+end
\ No newline at end of file
diff --git a/thys/XML/ROOT b/thys/XML/ROOT
--- a/thys/XML/ROOT
+++ b/thys/XML/ROOT
@@ -1,11 +1,12 @@
chapter AFP
session XML = "HOL-Library" +
options [timeout = 600]
sessions
Certification_Monads
Show
theories
Xmlt
+ Example_Application
document_files
"root.tex"
diff --git a/thys/XML/Xmlt.thy b/thys/XML/Xmlt.thy
--- a/thys/XML/Xmlt.thy
+++ b/thys/XML/Xmlt.thy
@@ -1,713 +1,578 @@
-(* Title: Xml
- Author: Christian Sternagel
- Author: René Thiemann
+(*
+Author: Akihisa Yamada
+Author: Christian Sternagel (
+Author: René Thiemann
*)
-
-section \XML Transformers for Extracting Data from XML Nodes\
-
theory Xmlt
-imports
- Xml
- Certification_Monads.Strict_Sum
- HOL.Rat
+ imports
+ "HOL-Library.Extended_Nat"
+ Show.Number_Parser
+ Certification_Monads.Strict_Sum
+ Show.Shows_Literal
+ Xml
begin
-type_synonym
- tag = string
-
-text \The type of transformers on xml nodes.\
-type_synonym
- 'a xmlt = "xml \ string +\<^sub>\ 'a"
-
-definition map :: "(xml \ ('e +\<^sub>\ 'a)) \ xml list \ 'e +\<^sub>\ 'a list"
-where
- [code_unfold]: "map = map_sum_bot"
-
-lemma map_mono [partial_function_mono]:
- fixes C :: "xml \ ('b \ ('e +\<^sub>\ 'c)) \ 'e +\<^sub>\ 'd"
- assumes C: "\y. y \ set B \ mono_sum_bot (C y)"
- shows "mono_sum_bot (\f. map (\y. C y f) B)"
- unfolding map_def by (auto intro: partial_function_mono C)
-
-hide_const (open) map
-
-fun "text" :: "tag \ string xmlt"
-where
- "text tag (XML n atts [XML_text t]) =
- (if n = tag \ atts = [] then return t
- else error (concat
- [''could not extract text for '', tag,'' from '', ''\'', show (XML n atts [XML_text t])]))"
-| "text tag xml = error (concat [''could not extract text for '', tag,'' from '', ''\'', show xml])"
-hide_const (open) "text"
-
-definition bool_of_string :: "string \ string +\<^sub>\ bool"
-where
- "bool_of_string s =
- (if s = ''true'' then return True
- else if s = ''false'' then return False
- else error (''cannot convert '' @ s @ '' into Boolean''))"
-
-fun bool :: "tag \ bool xmlt"
-where
- "bool tag node = Xmlt.text tag node \ bool_of_string"
-hide_const (open) bool
-
-definition fail :: "tag \ 'a xmlt"
-where
- "fail tag xml =
- error (concat
- [''could not transform the following xml element (expected '', tag, '')'', ''\'', show xml])"
-hide_const (open) fail
-
-definition guard :: "(xml \ bool) \ 'a xmlt \ 'a xmlt \ 'a xmlt"
-where
- "guard p p1 p2 x = (if p x then p1 x else p2 x)"
-hide_const (open) guard
-
-lemma guard_mono [partial_function_mono]:
- assumes p1: "\y. mono_sum_bot (p1 y)"
- and p2: "\y. mono_sum_bot (p2 y)"
- shows "mono_sum_bot (\g. Xmlt.guard p (\y. p1 y g) (\y. p2 y g) x)"
- by (cases x) (auto intro!: partial_function_mono p1 p2 simp: Xmlt.guard_def)
-
-fun leaf :: "tag \ 'a \ 'a xmlt"
-where
- "leaf tag x (XML name atts cs) =
- (if name = tag \ atts = [] \ cs = [] then return x
- else Xmlt.fail tag (XML name atts cs))" |
- "leaf tag x xml = Xmlt.fail tag xml"
-hide_const (open) leaf
-
-fun list1element :: "'a list \ 'a option"
-where
- "list1element [x] = Some x" |
- "list1element _ = None"
-
-fun singleton :: "tag \ 'a xmlt \ ('a \ 'b) \ 'b xmlt"
-where
- "singleton tag p1 f xml =
- (case xml of
- XML name atts cs \
- (if name = tag \ atts = [] then
- (case list1element cs of
- Some (cs1) \ p1 cs1 \ return \ f
- | None \ Xmlt.fail tag xml)
- else Xmlt.fail tag xml)
- | _ \ Xmlt.fail tag xml)"
-hide_const (open) singleton
-
-lemma singleton_mono [partial_function_mono]:
- assumes p: "\y. mono_sum_bot (p1 y)"
- shows "mono_sum_bot (\g. Xmlt.singleton t (\y. p1 y g) f x)"
- by (cases x, cases "list1element (Xml.children x)") (auto intro!: partial_function_mono p)
-
-fun list2elements :: "'a list \ ('a \ 'a) option"
-where
- "list2elements [x, y] = Some (x, y)" |
- "list2elements _ = None"
-
-fun pair :: "tag \ 'a xmlt \ 'b xmlt \ ('a \ 'b \ 'c) \ 'c xmlt"
-where
- "pair tag p1 p2 f xml =
- (case xml of
- XML name atts cs \
- (if name = tag \ atts = [] then
- (case list2elements cs of
- Some (cs1, cs2) \
- do {
- a \ p1 cs1;
- b \ p2 cs2;
- return (f a b)
- }
- | None \ Xmlt.fail tag xml)
- else Xmlt.fail tag xml)
- | _ \ Xmlt.fail tag xml)"
-hide_const (open) pair
-
-lemma pair_mono [partial_function_mono]:
- assumes "\y. mono_sum_bot (p1 y)"
- and "\y. mono_sum_bot (p2 y)"
- shows "mono_sum_bot (\g. Xmlt.pair t (\y. p1 y g) (\ y. p2 y g) f x)"
- using assms
- by (cases x, cases "list2elements (Xml.children x)") (auto intro!: partial_function_mono)
-
-fun list3elements :: "'a list \ ('a \ 'a \ 'a) option"
-where
- "list3elements [x, y, z] = Some (x, y, z)" |
- "list3elements _ = None"
-
-fun triple :: "string \ 'a xmlt \ 'b xmlt \ 'c xmlt \ ('a \ 'b \ 'c \ 'd) \ 'd xmlt"
-where
- "triple tag p1 p2 p3 f xml = (case xml of XML name atts cs \
- (if name = tag \ atts = [] then
- (case list3elements cs of
- Some (cs1, cs2, cs3) \
- do {
- a \ p1 cs1;
- b \ p2 cs2;
- c \ p3 cs3;
- return (f a b c)
- }
- | None \ Xmlt.fail tag xml)
- else Xmlt.fail tag xml)
- | _ \ Xmlt.fail tag xml)"
-
-lemma triple_mono [partial_function_mono]:
- assumes "\y. mono_sum_bot (p1 y)"
- and "\y. mono_sum_bot (p2 y)"
- and "\y. mono_sum_bot (p3 y)"
- shows "mono_sum_bot (\g. Xmlt.triple t (\y. p1 y g) (\ y. p2 y g) (\ y. p3 y g) f x)"
- using assms
- by (cases x, cases "list3elements (Xml.children x)", auto intro!: partial_function_mono)
+text \String literals in parser, for nicer generated code\
+type_synonym ltag = String.literal
-fun list4elements :: "'a list \ ('a \ 'a \ 'a \ 'a) option"
-where
- "list4elements [x, y, z, u] = Some (x, y, z, u)" |
- "list4elements _ = None"
-
-fun
- tuple4 ::
- "string \ 'a xmlt \ 'b xmlt \ 'c xmlt \ 'd xmlt \ ('a \ 'b \ 'c \ 'd \ 'e) \ 'e xmlt"
-where
- "tuple4 tag p1 p2 p3 p4 f xml =
- (case xml of
- XML name atts cs \
- (if name = tag \ atts = [] then
- (case list4elements cs of
- Some (cs1, cs2, cs3, cs4) \
- do {
- a \ p1 cs1;
- b \ p2 cs2;
- c \ p3 cs3;
- d \ p4 cs4;
- return (f a b c d)
- }
- | None \ Xmlt.fail tag xml)
- else Xmlt.fail tag xml)
- | _ \ Xmlt.fail tag xml)"
-
-lemma tuple4_mono [partial_function_mono]:
- assumes "\y. mono_sum_bot (p1 y)"
- and "\y. mono_sum_bot (p2 y)"
- and "\y. mono_sum_bot (p3 y)"
- and"\y. mono_sum_bot (p4 y)"
- shows "mono_sum_bot (\g. Xmlt.tuple4 t (\y. p1 y g) (\ y. p2 y g) (\ y. p3 y g) (\ y. p4 y g) f x)"
- using assms
- by (cases x, cases "list4elements (Xml.children x)") (auto intro!: partial_function_mono)
-
-fun list5elements :: "'a list \ ('a \ 'a \ 'a \ 'a \ 'a) option"
-where
- "list5elements [x, y, z, u, v] = Some (x, y, z, u, v)" |
- "list5elements _ = None"
-
-fun
- tuple5 ::
- "string \ 'a xmlt \ 'b xmlt \ 'c xmlt \ 'd xmlt \ 'e xmlt \
- ('a \ 'b \ 'c \ 'd \ 'e \ 'f) \ 'f xmlt"
-where
- "tuple5 tag p1 p2 p3 p4 p5 f xml =
- (case xml of
- XML name atts cs \
- (if name = tag \ atts = [] then
- (case list5elements cs of
- Some (cs1,cs2,cs3,cs4,cs5) \
- do {
- a \ p1 cs1;
- b \ p2 cs2;
- c \ p3 cs3;
- d \ p4 cs4;
- e \ p5 cs5;
- return (f a b c d e)
- }
- | None \ Xmlt.fail tag xml)
- else Xmlt.fail tag xml)
- | _ \ Xmlt.fail tag xml)"
-
-lemma tuple5_mono [partial_function_mono]:
- assumes "\y. mono_sum_bot (p1 y)"
- and "\y. mono_sum_bot (p2 y)"
- and "\y. mono_sum_bot (p3 y)"
- and "\y. mono_sum_bot (p4 y)"
- and "\y. mono_sum_bot (p5 y)"
- shows "mono_sum_bot (\g. Xmlt.tuple5 t (\y. p1 y g) (\ y. p2 y g) (\ y. p3 y g) (\ y. p4 y g) (\ y. p5 y g) f x)"
- using assms
- by (cases x, cases "list5elements (Xml.children x)") (auto intro!: partial_function_mono)
+datatype 'a xml_error = TagMismatch "ltag list" | Fatal 'a
+text \
+ @{term "TagMismatch tags"} represents tag mismatch, expecting one of @{term tags} but
+ something else is encountered.
+\
-fun list6elements :: "'a list \ ('a \ 'a \ 'a \ 'a \ 'a \ 'a) option"
-where
- "list6elements [x, y, z, u, v, w] = Some (x, y, z, u, v, w)" |
- "list6elements _ = None"
-
-fun
- tuple6 ::
- "string \ 'a xmlt \ 'b xmlt \ 'c xmlt \ 'd xmlt \ 'e xmlt \ 'f xmlt \
- ('a \ 'b \ 'c \ 'd \ 'e \ 'f \ 'g) \ 'g xmlt"
-where
- "tuple6 tag p1 p2 p3 p4 p5 p6 f xml =
- (case xml of
- XML name atts cs \
- (if name = tag \ atts = [] then
- (case list6elements cs of
- Some (cs1,cs2,cs3,cs4,cs5,cs6) \
- do {
- a \ p1 cs1;
- b \ p2 cs2;
- c \ p3 cs3;
- d \ p4 cs4;
- e \ p5 cs5;
- ff \ p6 cs6;
- return (f a b c d e ff)
- }
- | None \ Xmlt.fail tag xml)
- else Xmlt.fail tag xml)
- | _ \ Xmlt.fail tag xml)"
+lemma xml_error_mono [partial_function_mono]:
+ assumes p1: "\tags. mono_option (p1 tags)"
+ and p2: "\x. mono_option (p2 x)"
+ and f: "mono_option f"
+ shows "mono_option (\g. case s of TagMismatch tags \ p1 tags g | Fatal x \ p2 x g)"
+ using assms by (cases s, auto intro!:partial_function_mono)
-lemma tuple6_mono [partial_function_mono]:
- assumes "\y. mono_sum_bot (p1 y)"
- and "\y. mono_sum_bot (p2 y)"
- and "\y. mono_sum_bot (p3 y)"
- and "\y. mono_sum_bot (p4 y)"
- and "\y. mono_sum_bot (p5 y)"
- and "\y. mono_sum_bot (p6 y)"
- shows "mono_sum_bot (\g. Xmlt.tuple6 t (\y. p1 y g) (\ y. p2 y g) (\ y. p3 y g) (\ y. p4 y g) (\ y. p5 y g) (\ y. p6 y g) f x)"
- using assms
- by (cases x, cases "list6elements (Xml.children x)") (auto intro!: partial_function_mono)
-
-fun optional :: "tag \ 'a xmlt \ ('a option \ 'b) \ 'b xmlt"
-where
- "optional tag p1 f (XML name atts cs) =
- (let l = length cs in
- (if name = tag \ atts = [] \ l \ 0 \ l \ 1 then do {
- if l = 1 then do {
- x1 \ p1 (cs ! 0);
- return (f (Some x1))
- } else return (f None)
- } else Xmlt.fail tag (XML name atts cs)))" |
- "optional tag p1 f xml = Xmlt.fail tag xml"
+text \