使用OCaml格式模块输出xml

时间:2023-01-14 10:45:49

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执行换行。对于@或@,布局将尽可能地适合一行——但是一旦它破坏了一行,它将在同一个打印框中破坏后续的行。实验。看到文档和指南。