# Html encoding of string

**URL:** <https://discuss.ocaml.org/t/html-encoding-of-string/4289>\
**Category:** Learning\
**Created:** [August 26, 2019, 6:53pm UTC](https://discuss.ocaml.org/t/html-encoding-of-string/4289 "2019-08-26T18:53:02Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![umutacar](https://avatars.discourse-cdn.com/v4/letter/u/7993a0/32.png) [@umutacar](https://discuss.ocaml.org/u/umutacar)\
**Post date:** [August 26, 2019, 6:53pm UTC](https://discuss.ocaml.org/t/html-encoding-of-string/4289/1 "2019-08-26T18:53:02Z")

</div>

I have a string that has html-special characters such as “&” (and others such as quote) and I would like to espace these to their html equivalent. How could I do this?

Example: a string like this (note link is not meant to work) [https://www.youtube.com/watch?v=something&list=somethingelse&index=2&t=0s](https://www.youtube.com/watch?v=something&list=somethingelse&index=2&t=0s)

---

<div class="post-metadata">

**Author:** ![Stephane\_Glondu](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/stephane_glondu/32/1686_2.png) [@Stephane\_Glondu](https://discuss.ocaml.org/u/Stephane_Glondu)\
**Post date:** [August 27, 2019, 2:19pm UTC](https://discuss.ocaml.org/t/html-encoding-of-string/4289/2 "2019-08-27T14:19:21Z")

</div>

You can use ocamlnet: [http://projects.camlcity.org/projects/dl/ocamlnet-4.1.6/doc/html-main/Netencoding.Html.html](http://projects.camlcity.org/projects/dl/ocamlnet-4.1.6/doc/html-main/Netencoding.Html.html)

---

<div class="post-metadata">

**Author:** ![lindig](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lindig/32/532_2.png) [@lindig](https://discuss.ocaml.org/u/lindig)\
**Post date:** [August 27, 2019, 7:49pm UTC](https://discuss.ocaml.org/t/html-encoding-of-string/4289/3 "2019-08-27T19:49:01Z")

</div>

You could implement a scanner (module) using OCamlLex to do that: based on regular expressions, it scans the string and builds a buffer with the critical characters escaped. It’s a bit unusual but quite efficient.

```auto
{
    (* ocamllex scan.mll && ocamlc -o scan scan.ml *)

    module L = Lexing 
    module B = Buffer

let get = L.lexeme
let sprintf = Printf.sprintf

let position lexbuf =
    let p = lexbuf.L.lex_curr_p in
        sprintf "%s:%d:%d" 
        p.L.pos_fname p.L.pos_lnum (p.L.pos_cnum - p.L.pos_bol)

exception Error of string
let error lexbuf fmt = 
    Printf.kprintf (fun msg -> 
        raise (Error ((position lexbuf)^" "^msg))) fmt

}

rule escape b = parse
| '&' { B.add_string b "&amp;"; escape b lexbuf } 
| '"' { B.add_string b "&quot;"; escape b lexbuf } 
| '\'' { B.add_string b "&apos;"; escape b lexbuf }
| '>' { B.add_string b "&gt;"; escape b lexbuf }
| '<' { B.add_string b "&lt;"; escape b lexbuf }
| [^'&' '"' '\'' '>' '<']+ 
            { B.add_string b @@ get lexbuf
            ; escape b lexbuf
            }
| eof { let x = B.contents b in B.clear b; x }
| _ { error lexbuf 
                "don't know how to quote: %s" (get lexbuf) }

{
let escape str = escape (B.create 100) (L.from_string str)

let main () =
  let args = Sys.argv |> Array.to_list |> List.tl in
  args |> List.iter (fun str -> escape str |> print_endline)

let () = main () (* call main function on startup *)
}

```

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [August 27, 2019, 8:23pm UTC](https://discuss.ocaml.org/t/html-encoding-of-string/4289/4 "2019-08-27T20:23:23Z")

</div>

Here’s a function that escapes certain characters of a string and adds the result in a `Buffer.t` value. It should be easy to adapt to your wishes as long as your escapes are of the form `char -> string`:

```ocaml
let add_esc : Buffer.t -> string -> unit = fun b s ->
  let add = Buffer.add_string in                      
  let len = String.length s in
  let max_idx = len - 1 in
  let flush b start i =
    if start < len then Buffer.add_substring b s start (i - start)
  in
  let rec loop start i =
    if i > max_idx then flush b start i else
    let next = i + 1 in
    match String.get s i with
    | '&' -> flush b start i; add b "&amp;"; loop next next
    | '<' -> flush b start i; add b "&lt;"; loop next next
    | '>' -> flush b start i; add b "&gt;"; loop next next
    | '\'' -> flush b start i; add b "&apos;"; loop next next
    | '\"' -> flush b start i; add b "&quot;"; loop next next
    | '@' -> flush b start i; add b "&commat;"; loop next next
    | c -> loop start next
  in
  loop 0 0

```

---

<div class="post-metadata">

**Author:** ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)\
**Post date:** [August 28, 2019, 2:36am UTC](https://discuss.ocaml.org/t/html-encoding-of-string/4289/5 "2019-08-28T02:36:15Z")

</div>

Are you looking to produce an HTML encoding, that is, text that, when viewed in a browser as HTML, will display the source text? Or are you looking to do URL-encoding? That is, the component parts can be taken apart from the encoded URL, and once decoded, will have the values you started with ?

In the latter case, there’s Netencoding.Url, which has two utility functions to encode and decode URLs and their parameters.

---

<div class="post-metadata">

**Author:** ![umutacar](https://avatars.discourse-cdn.com/v4/letter/u/7993a0/32.png) [@umutacar](https://discuss.ocaml.org/u/umutacar)\
**Post date:** [September 7, 2019, 6:45pm UTC](https://discuss.ocaml.org/t/html-encoding-of-string/4289/6 "2019-09-07T18:45:41Z")

</div>

Thank you. this is exactly what i was looking for!

---

<div class="post-metadata">

**Author:** ![umutacar](https://avatars.discourse-cdn.com/v4/letter/u/7993a0/32.png) [@umutacar](https://discuss.ocaml.org/u/umutacar)\
**Post date:** [September 7, 2019, 6:52pm UTC](https://discuss.ocaml.org/t/html-encoding-of-string/4289/7 "2019-09-07T18:52:13Z")

</div>

Thank you everybody for the suggested solutions! I was looking for a library function that I can call and the NetEncoding solutions seems to have worked.
