ساخت خروجی XML با dream-html

مدتی است که من یک کتابخانه OCaml به نام dream-html نگهداری می کنم. این کتابخانه در درجه اول برای ارائه HTML، SVG و MathML به درستی ساخته شده است. اخیراً قابلیت رندر کردن نشانهگذاری XML به خوبی شکل گرفته را اضافه کردم که قوانین کمی متفاوت از HTML دارد. به عنوان مثال، در HTML اگر می خواهید خالی بنویسید div
برچسب، شما انجام می دهید: . But according to the rules of XML, you could also write
ie a self-closing tag, however HTML 5 does not have the concept of self-closing tags!
So by having the library take care of these subtle but crucial details, you can just concentrate on writing code that generates the markup. Of course, this has many other advantages too, but in this post I will just look at XML.
It turns out that often we need to serialize some data into XML format, for storage or communication purposes. There are a few packages in the OCaml ecosystem which handle XML, however I think dream-html actually does it surprisingly well now. Let’s take a look.
But first, a small clarification about the dream-html package itself. Recently I split it up into two packages:
-
pure-html
تمام قابلیت های مورد نیاز برای نوشتن HTML و XML معتبر را دارد -
dream-html
همه موارد فوق را دارد، به علاوه مقداری ادغام با چارچوب وب Dream برای سهولت استفاده.
همانطور که ممکن است تصور کنید، دلیل تقسیم اجازه استفاده از عملکرد HTML/XML بسته بدون نیاز به کشیدن کل مخروط وابستگی Dream بود، که بسیار بزرگ است، به خصوص اگر از مخروط وابستگی متفاوتی استفاده کنید. خوب. بنابراین pure-html
فقط به uri
بسته ای برای کمک به ساخت رشته های URI صحیح.
برای شروع استفاده از آن، فقط نصب کنید: opam install pure-html
و به خود اضافه کنید dune
فایل: (libraries pure-html)
حال، بیایید به مثالی نگاه کنیم که چگونه می توانید از آن برای ساخت XML استفاده کنید. فرض کنید نوع زیر را دارید:
type person = {
name : string;
email : string;
}
و شما باید آن را به صورت سریال XML به صورت زیر انجام دهید:
name="Bob" email="bob@info.com"/>
بیایید با استفاده از یک سریال ساز بنویسیم pure-html
بسته:
open Pure_html
let person_xml =
let person = std_tag "person"
and name = string_attr "name"
and email = string_attr "email" in
fun { name = n; email = e } -> person [name "%s" n; email "%s" e] []
بیایید آن را آزمایش کنیم:
$ utop -require pure-html
# open Pure_html;;
# let pp = pp_xml ~header:true;;
val pp : Format.formatter -> node -> unit =
# #install_printer pp;;
# type person = {
name : string;
email : string;
};;
type person = { name : string; email : string; }
# let person_xml =
let person = std_tag "person"
and name = string_attr "name"
and email = string_attr "email" in
fun { name = n; email = e } -> person [name "%s" n; email "%s" e] [];;
val person_xml : person -> node =
# person_xml { name = "Bob"; email = "bob@example.com" };;
- : node =
خوب خوب، پس ما person
رکورد به این روش خاص سریال می شود. اما، اگر بخواهیم آن را سریالی کنیم، چه میشود:
Bob
bob@example.com
از این گذشته، این یک روش رایج برای قالببندی رکوردها در XML است. بیایید سریال ساز را به این سبک بنویسیم:
let person_xml =
let person = std_tag "person"
and name = std_tag "name"
and email = std_tag "email" in
fun { name = n; email = e } ->
person [] [
name [] [txt "%s" n];
email [] [txt "%s" e];
]
بیایید آن را امتحان کنیم:
# let person_xml =
let person = std_tag "person"
and name = std_tag "name"
and email = std_tag "email" in
fun { name = n; email = e } ->
person [] [
name [] [txt "%s" n];
email [] [txt "%s" e];
];;
val person_xml : person -> node =
# person_xml { name = "Bob"; email = "bob@example.com" };;
- : node =
Bob bob@example.com
به نظر خوب میاد! بیایید توابع را بررسی کنیم pure-html
بسته مورد استفاده در اینجا برای رسیدن به این.
std_tag
این تابع به ما امکان می دهد یک تگ سفارشی تعریف کنیم: let person = std_tag "person"
. توجه داشته باشید که اضافه کردن فضای نام امری بی اهمیت است: let person = std_tag "my:person"
.
string_attr
این به ما اجازه می دهد تا یک ویژگی سفارشی را تعریف کنیم که a را می گیرد رشته ظرفیت ترابری: let name = string_attr "name"
. باز هم اضافه کردن فضای نام آسان است: let name = string_attr "my:name"
.
توابع تعریف ویژگی دیگری نیز وجود دارد که اجازه می دهد int
محموله ها و غیره برای جزئیات به اسناد بسته مراجعه کنید.
pp_xml
این به ما امکان می دهد چاپگری را تعریف کنیم که XML را مطابق قوانین نحوی آن به درستی رندر می کند:
let pp = pp_xml ~header:true
اختیاری header
آرگومان به ما اجازه می دهد مشخص کنیم که آیا می خواهیم همیشه سربرگ XML را چاپ کنیم یا خیر. در بسیاری از موارد سریال سازی، ما انجام می دهیم.
همچنین یک تابع مشابه وجود دارد که به جای تعریف a چاپگر، فقط تبدیل می کند گره ساخته شده در یک رشته به طور مستقیم: to_xml
.
نتیجه
با این توابع اساسی، ممکن است دقیقا کنترل کنید که XML سریالی چگونه به نظر می رسد. توجه داشته باشید که dream-html
و pure-html
فقط پشتیبانی سریال سازی داده ها به فرمت XML، و نه سریال زدایی یعنی تجزیه XML. برای آن، بسته های دیگری وجود دارد!