格式模块中的框和 XML
Boxes and XML in Format module
我想在 Format module 中使用框和 XML 打印输出。
创意格式如下:
<Events>
<Event>
<name> haha </name>
<name> haha </name>
</Event>
<Event>
<name> lili </name>
<name> lili </name>
</Event>
<Event>
<name> lolo </name>
<name> lolo </name>
</Event>
</Events>
目前我的代码如下,它没有完全按照我的预期打印(我省略了不正确的结果)。
(* in event.ml *)
let print_name (fmt: formatter) (x: t) : unit =
Format.open_tag "Name";
Format.fprintf fmt "%s" (get_name x);
Format.close_tag ()
(* in events.ml *)
let print (fmt: formatter) (x: t) : unit =
let print (fmt: formatter) (x: t) : unit =
List.iter
(fun m ->
Format.open_tag "Event";
Format.fprintf fmt "@,@[<v 4>%a@,%a@," Event.print_name m
Event.print_name m; (* print twice *)
Format.close_tag ();
Format.fprintf fmt "@,@]")
x
in
Format.open_tag "Events";
Format.fprintf fmt "@,@[<v 4>%a@]@," print x;
Format.close_tag ()
(* in main.ml *)
Format.fprintf Format.std_formatter "%a" Events.print x
我不确定我是否理解这个框,尤其是当涉及 XML 时。有谁知道如何正确编写这些格式?
Format在打印带缩进的数据时很有用,但它的缩进算法有点棘手,很难完美模拟其他缩进策略。也许自己处理缩进级别更容易。
这样的怎么样?
let format, format_list = Format.(fprintf, pp_print_list) (* sorry, hate these cryptic names *)
type xml =
| Tag of string * xml list
| String of string
let rec format_xml f = function
| Tag (name, body) ->
let format_body = format_list format_xml in
format f "@[<hv 3><%s>@,%a@;<0 -3></%s>@]" name format_body body name
| String text -> format f "%s" text
let tag name body = Tag (name, body)
let name s = tag "name" [String s]
let () =
Format.set_margin 50;
let xml = tag "Events" [
tag "Event" [
name "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; name "b"; name "c";
];
tag "Event" [name "a"; name "b"; name "c"];
tag "Event" [name "a"; name "b"];
tag "Event" [];
] in
format_xml Format.std_formatter xml
这是上面测试用例的输出:
<Events>
<Event>
<name>
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</name>
<name>b</name>
<name>c</name>
</Event>
<Event>
<name>a</name>
<name>b</name>
<name>c</name>
</Event>
<Event><name>a</name><name>b</name></Event>
<Event></Event>
</Events>
通过调整格式字符串 @[<hv 3><%s>@,%a@;<0 -3></%s>@]
,您可以强制其水平或垂直布局。要获得您指定的确切格式,您需要默认标签框是垂直的 <v 3>
,但特殊情况下您的 name
标签框是水平的 <h>
。但是,我决定提供一个更通用的示例。
让我解释一下。 @[<hv 3>
打开一个框,它可以在水平 h
和垂直 v
布局之间交替,具体取决于框的内容是否适合一行,在我们的例子中是 50 个字符(请参阅Format.set_margin 50
)。 @[<hv 3>
中的3
是缩进级别。 <%s>
是开始的 XML 标签,</%s>
——结束。开始标记在框内,但没有缩进,因为缩进仅在像 @,
这样的中断提示上引入。我们希望结束标记缩进 而不是 ,这就是为什么我们引入了一个中断提示 @;<0 -3>
,它在垂直布局的情况下取消缩进 -3
,但引入了 0
横向空格。请注意,我正在使用的 Format.pp_print_list
在列表元素之间引入了中断提示 @,
(默认情况下)。
希望这有用。如果您有任何问题,请告诉我。
您使用方框处理缩进。要实现此缩进,您需要使用如下框(括号划定框):
((<tag>contents)</tag>)
请注意框和标签的嵌套方式不同。 Gasoline中使用了此技术,请参阅:
- testsuite 用法示例
- implementation
请注意,来自 Gasoline 的 authorkit 对于编写简单的临时 SGML 很有用文件,但在高级案例中,来自 ocsigen 项目的库可能更有用(但更难使用)。
我想在 Format module 中使用框和 XML 打印输出。 创意格式如下:
<Events>
<Event>
<name> haha </name>
<name> haha </name>
</Event>
<Event>
<name> lili </name>
<name> lili </name>
</Event>
<Event>
<name> lolo </name>
<name> lolo </name>
</Event>
</Events>
目前我的代码如下,它没有完全按照我的预期打印(我省略了不正确的结果)。
(* in event.ml *)
let print_name (fmt: formatter) (x: t) : unit =
Format.open_tag "Name";
Format.fprintf fmt "%s" (get_name x);
Format.close_tag ()
(* in events.ml *)
let print (fmt: formatter) (x: t) : unit =
let print (fmt: formatter) (x: t) : unit =
List.iter
(fun m ->
Format.open_tag "Event";
Format.fprintf fmt "@,@[<v 4>%a@,%a@," Event.print_name m
Event.print_name m; (* print twice *)
Format.close_tag ();
Format.fprintf fmt "@,@]")
x
in
Format.open_tag "Events";
Format.fprintf fmt "@,@[<v 4>%a@]@," print x;
Format.close_tag ()
(* in main.ml *)
Format.fprintf Format.std_formatter "%a" Events.print x
我不确定我是否理解这个框,尤其是当涉及 XML 时。有谁知道如何正确编写这些格式?
Format在打印带缩进的数据时很有用,但它的缩进算法有点棘手,很难完美模拟其他缩进策略。也许自己处理缩进级别更容易。
这样的怎么样?
let format, format_list = Format.(fprintf, pp_print_list) (* sorry, hate these cryptic names *)
type xml =
| Tag of string * xml list
| String of string
let rec format_xml f = function
| Tag (name, body) ->
let format_body = format_list format_xml in
format f "@[<hv 3><%s>@,%a@;<0 -3></%s>@]" name format_body body name
| String text -> format f "%s" text
let tag name body = Tag (name, body)
let name s = tag "name" [String s]
let () =
Format.set_margin 50;
let xml = tag "Events" [
tag "Event" [
name "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; name "b"; name "c";
];
tag "Event" [name "a"; name "b"; name "c"];
tag "Event" [name "a"; name "b"];
tag "Event" [];
] in
format_xml Format.std_formatter xml
这是上面测试用例的输出:
<Events>
<Event>
<name>
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</name>
<name>b</name>
<name>c</name>
</Event>
<Event>
<name>a</name>
<name>b</name>
<name>c</name>
</Event>
<Event><name>a</name><name>b</name></Event>
<Event></Event>
</Events>
通过调整格式字符串 @[<hv 3><%s>@,%a@;<0 -3></%s>@]
,您可以强制其水平或垂直布局。要获得您指定的确切格式,您需要默认标签框是垂直的 <v 3>
,但特殊情况下您的 name
标签框是水平的 <h>
。但是,我决定提供一个更通用的示例。
让我解释一下。 @[<hv 3>
打开一个框,它可以在水平 h
和垂直 v
布局之间交替,具体取决于框的内容是否适合一行,在我们的例子中是 50 个字符(请参阅Format.set_margin 50
)。 @[<hv 3>
中的3
是缩进级别。 <%s>
是开始的 XML 标签,</%s>
——结束。开始标记在框内,但没有缩进,因为缩进仅在像 @,
这样的中断提示上引入。我们希望结束标记缩进 而不是 ,这就是为什么我们引入了一个中断提示 @;<0 -3>
,它在垂直布局的情况下取消缩进 -3
,但引入了 0
横向空格。请注意,我正在使用的 Format.pp_print_list
在列表元素之间引入了中断提示 @,
(默认情况下)。
希望这有用。如果您有任何问题,请告诉我。
您使用方框处理缩进。要实现此缩进,您需要使用如下框(括号划定框):
((<tag>contents)</tag>)
请注意框和标签的嵌套方式不同。 Gasoline中使用了此技术,请参阅:
- testsuite 用法示例
- implementation
请注意,来自 Gasoline 的 authorkit 对于编写简单的临时 SGML 很有用文件,但在高级案例中,来自 ocsigen 项目的库可能更有用(但更难使用)。