如何将简单文档表示为 s-exp?

How to represent a simple document as an s-exp?

我正在尝试了解如何在 s 表达式中表达一个简单的文档。这就是我的意思。假设我有这个简单的 html 结构:

<h1>Document Title</h1>
<p>Paragraph with some text.</p>
<p>Paragraph with some <strong>bold</strong> text.</p>

另外假设我可以接受丢失原始标签出处并且只想保留结构。这怎么能用sexp来表达呢?我最初的尝试(使用 clojure)看起来像这样,但我不确定它是否正确:

(def sexp-doc '("Document Title"
                ("" ())
                ("This is a paragraph with some text." ())
                ("" ())
                ("This is a paragraph with" ("bold" ()) ("text." ()))))

S-expressions 是树,因此下面的示例可以表示 html 文档:

'(html (head (title "some title") (meta "some meta"))
       (body (h1 "Hello, World!") (p "This is the" (strong "body") "text"))

属性可以由第一个元素带有标签 attributes:

的每个元素实现
'(p (attributes 
     (attribute (name "style") 
                (value "margin: 10px;"))
     (attribute (name "title") 
                (value "Ingress"))) 
    "Once upon a time ....)

这并不漂亮,因为属性实际上代表每个需要结构化的标签的一级键值数据。我认为 W3C 曾一度确实提出过类似的建议,但它使文档变得更加复杂。

对于这种情况,我建议使用 Hiccup's syntax

(require '[clojure.string :as str]
         '[hiccup.core :as hiccup])

(def document
  [[:h1 "Document Title"]
   [:p "Paragraph with some text."]
   [:p "Paragraph with some " [:strong "bold"] " text."]])

(println (str/join "\n" (map #(hiccup/html %) document)))
;; <h1>Document Title</h1>
;; <p>Paragraph with some text.</p>
;; <p>Paragraph with some <strong>bold</strong> text.</p>
;;=> nil

如果您不需要转换回 HTML 字符串,那么显然您不需要 Hiccup 依赖项;我只是把它放在这里是为了证明这三个向量中的每一个都是有效的 Hiccup。

由于此语法使用向量而不是列表,因此您无需引用内容或直接使用 list 函数,这为您带来了两个优势:

  • 如果引用东西,就不能在"Hiccup literals"
  • 中调用函数构造内部形式
  • 如果您必须为每个表单调用 list 函数,它会变得拥挤且难以阅读

如果您想使用自己的标签来代替现有的 HTML 标签,也没有什么能阻止您在 Hiccup 的语法中这样做。