I'm trying to output XML with OCaml with indentation :
我试着输出带有缩进的OCaml的XML:
<document>
<tag>
<undertag/>
<undertag/>
</tag>
<tag>
<undertag/>
</tag>
</document>
I'm trying with Format but I can't get the expected result...
我正在尝试格式,但我无法得到预期的结果…
Format.printf "@.";
Format.printf
"@[<hv>@[<hv 2>(------------------------------------------------------------------------\
@[<hv>@[<hv 2>(------------------------------------------------------------------------\
@[<hv>@[<hv 2>(------------------------------------------------------------------------\
@]@,)@]@]@,)@]@]@,)@]";
Format.printf "@."
Does output :
输出:
(------------------------------------------------------------------------
(------------------------------------------------------------------------
(------------------------------------------------------------------------
)
)
)
But
但
fp "@.";
fp "@[<hv>@[<hv 2><document>";
fp "@[<hv>@[<hv 2><cfun>";
fp "@[<hv>@[<hv 2><cst/>@]@]";
fp "@]@,</cfun>@]";
fp "@]@,</document>@]";
fp "@.";
Where fp = Format.printf
outputs <document><cfun><cst/></cfun></document>
(all in one line !).
fp =格式。printf输出
How should I do ?
我该怎么办?
Thanks.
谢谢。
4 个解决方案
#1
3
Example using xmlm (intentionally procedural, use helper functions suitable for your case):
使用xmlm的示例(有意使用过程函数,使用适合您的情况的帮助函数):
let out = Xmlm.make_output ~indent:(Some 4) (`Channel stdout) in
Xmlm.output out (`Dtd None);
Xmlm.output out (`El_start (("", "document"), []));
Xmlm.output out (`El_start (("", "tag"), []));
Xmlm.output out (`El_start (("", "undertag"), [(("", "id"), "1")]));
Xmlm.output out (`Data "data");
Xmlm.output out `El_end;
Xmlm.output out (`El_start (("", "undertag"), [(("", "id"), "2")]));
Xmlm.output out `El_end;
Xmlm.output out `El_end;
Xmlm.output out `El_end
Note the indent parameter.
注意缩进参数。
The output:
输出:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<tag>
<undertag id="1">
data
</undertag>
<undertag id="2"/>
</tag>
</document>
#2
2
A friend showed me a way to do it with vertical boxes. The following outputs just fine : @[<v 0>@,<xml>@,<document>@[<v 2>@,<tag>@[<v 2>@,<el>@,<el>@,<el>@]@,</tag>@]@,</document>@]
.
一个朋友给我展示了一种垂直盒子的方法。以下输出很好:@[v < 0 > @ < xml > @, <文件> @[v < 2 > @ <标记> @[v < 2 > @ < el > @,< el > @ < el > @]@,< /标签> @]@,< /文档> @]。
Hope this can help.
希望这可以帮助。
#3
2
You can do the following using Format module:
您可以使用Format模块完成以下操作:
Let's say you have this XML type,
假设你有这种XML类型,
type xml =
| Tag of string * xml list
| String of string
let tag name body = Tag (name, body)
Here's a pretty-printer for it:
这里有一个漂亮的打印机:
let format, format_list = Format.(fprintf, pp_print_list)
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
Here's a test case similar to yours:
这里有一个类似于你的测试用例:
let () =
Format.set_margin 30;
let xml = tag "document" [
tag "tag" [tag "undertag" [String "hello"]];
tag "tag" [tag "undertag" []];
] in
format_xml Format.std_formatter xml
It prints the following:
它打印以下:
<document>
<tag>
<undertag>
hello
</undertag>
</tag>
<tag>
<undertag></undertag>
</tag>
</document>
Another answer of mine has some more explanation about the format string that is used: Boxes and XML in Format module
我的另一个答案是关于使用的格式字符串的更多解释:格式模块中的box和XML
#4
0
You can use @\n
to enforce line breaks. For @,
or @
the layout will try to fit as much in a line as possible -- but once it breaks a line, it will break subsequent lines in the same printing box. Experiment with it. See documentation and guidelines.
您可以使用@\n执行换行。对于@或@,布局将尽可能地适合一行——但是一旦它破坏了一行,它将在同一个打印框中破坏后续的行。实验。看到文档和指南。
#1
3
Example using xmlm (intentionally procedural, use helper functions suitable for your case):
使用xmlm的示例(有意使用过程函数,使用适合您的情况的帮助函数):
let out = Xmlm.make_output ~indent:(Some 4) (`Channel stdout) in
Xmlm.output out (`Dtd None);
Xmlm.output out (`El_start (("", "document"), []));
Xmlm.output out (`El_start (("", "tag"), []));
Xmlm.output out (`El_start (("", "undertag"), [(("", "id"), "1")]));
Xmlm.output out (`Data "data");
Xmlm.output out `El_end;
Xmlm.output out (`El_start (("", "undertag"), [(("", "id"), "2")]));
Xmlm.output out `El_end;
Xmlm.output out `El_end;
Xmlm.output out `El_end
Note the indent parameter.
注意缩进参数。
The output:
输出:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<tag>
<undertag id="1">
data
</undertag>
<undertag id="2"/>
</tag>
</document>
#2
2
A friend showed me a way to do it with vertical boxes. The following outputs just fine : @[<v 0>@,<xml>@,<document>@[<v 2>@,<tag>@[<v 2>@,<el>@,<el>@,<el>@]@,</tag>@]@,</document>@]
.
一个朋友给我展示了一种垂直盒子的方法。以下输出很好:@[v < 0 > @ < xml > @, <文件> @[v < 2 > @ <标记> @[v < 2 > @ < el > @,< el > @ < el > @]@,< /标签> @]@,< /文档> @]。
Hope this can help.
希望这可以帮助。
#3
2
You can do the following using Format module:
您可以使用Format模块完成以下操作:
Let's say you have this XML type,
假设你有这种XML类型,
type xml =
| Tag of string * xml list
| String of string
let tag name body = Tag (name, body)
Here's a pretty-printer for it:
这里有一个漂亮的打印机:
let format, format_list = Format.(fprintf, pp_print_list)
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
Here's a test case similar to yours:
这里有一个类似于你的测试用例:
let () =
Format.set_margin 30;
let xml = tag "document" [
tag "tag" [tag "undertag" [String "hello"]];
tag "tag" [tag "undertag" []];
] in
format_xml Format.std_formatter xml
It prints the following:
它打印以下:
<document>
<tag>
<undertag>
hello
</undertag>
</tag>
<tag>
<undertag></undertag>
</tag>
</document>
Another answer of mine has some more explanation about the format string that is used: Boxes and XML in Format module
我的另一个答案是关于使用的格式字符串的更多解释:格式模块中的box和XML
#4
0
You can use @\n
to enforce line breaks. For @,
or @
the layout will try to fit as much in a line as possible -- but once it breaks a line, it will break subsequent lines in the same printing box. Experiment with it. See documentation and guidelines.
您可以使用@\n执行换行。对于@或@,布局将尽可能地适合一行——但是一旦它破坏了一行,它将在同一个打印框中破坏后续的行。实验。看到文档和指南。