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

Clojure 如何将简单文档表示为s-exp?,clojure,documents,s-expression,Clojure,Documents,S Expression,我试图理解如何用s表达式表达一个简单的文档。这就是我的意思。假设我有一个简单的html结构: <h1>Document Title</h1> <p>Paragraph with some text.</p> <p>Paragraph with some <strong>bold</strong> text.</p> S表达式是树,因此下面的示例可以是html文档的表示: '(html (head (

我试图理解如何用s表达式表达一个简单的文档。这就是我的意思。假设我有一个简单的html结构:

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

S表达式是树,因此下面的示例可以是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曾经提出过类似的建议,但它使文档更加复杂

S表达式是树,因此下面的示例可以表示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曾经提出过类似的建议,但它使文档更加复杂

我建议在这种情况下使用:

(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
(需要'[clojure.string:as str]
“[hiccup.core:as hiccup])
(def文件
[:h1“文件标题”]
[:p“有文字的段落。”]
[:p“段落加上一些”[:强“粗体”]“文本”。]]
(println(str/join“\n”(map#(hiccup/html%)文档)))
;; 文件标题
;;  有文字的段落

;; 带有一些粗体文本的段落

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

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

  • 如果你引用一些东西,就不能调用函数来构造“Hiccup literals”中的内部形式
  • 如果您必须为每个表单调用
    list
    函数,它会变得拥挤且难以阅读
如果您想使用自己的标记来代替现有的HTML标记,那么在Hiccup的语法中也没有什么可以阻止您这样做。

我建议您在这样的情况下使用:

(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
(需要'[clojure.string:as str]
“[hiccup.core:as hiccup])
(def文件
[:h1“文件标题”]
[:p“有文字的段落。”]
[:p“段落加上一些”[:强“粗体”]“文本”。]]
(println(str/join“\n”(map#(hiccup/html%)文档)))
;; 文件标题
;;  有文字的段落

;; 带有一些粗体文本的段落

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

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

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

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

我实际上试图用单个标记来表示文档内容,然后将HTML数据(假定有)存储在元数据属性中。但是仍然要弄清楚这会是什么样子。@fraxture只有一个标记,您无法保留文档结构。您不需要将您的结构建模为完全MIMICK html,只需按照您需要的细节级别,您可以按顺序嵌入逻辑。例如,只允许一个标题,那么段落就可以用一个没有任何标记的文本列表来完成,因为你可以根据自己的规则重新创建html。我猜结构的意思是:标题,可能是节,然后是段落。你在这里说:“只允许一个标题,那么段落就可以用一个没有任何标签的文本列表来完成”似乎是我想要走的方向。但我不确定这会是什么样子。我上面的例子有缺陷吗?如果是这样,你能给我一个替代的例子吗?@fraxture一点也不,但我不明白空列表和带空字符串的列表是用来做什么的。您的文档IMO的最低版本应该是
”(“文档标题”(“这是一个带有一些文本的段落”)(“这是一个带有”(b“bold”)“text.”的段落)
。本例中的自定义规则是,只有顶部元素列表是段落,并且只能有一个标题(第一个元素)。下面的列表是样式或其他受支持的结构,如
b
标记。感谢您的示例。这很有帮助。还有几个问题--消除我心中的困惑。你这里提到的“规则”是你强加的规则,对吗?关于您提供的结构的假设?“顶级元素列表”是什么意思?这个
b
标记,同样,是一个你说在你的规则中会被“支持”的标记,而不是sexps的一部分,对吗?我实际上想做的是用一个标记来表示文档内容,然后将html数据(假定有)存储在元数据属性中。但是仍然要弄清楚这会是什么样子。@fraxture只有一个标记,您无法保留文档结构。您不需要将您的结构建模为完全MIMICK html,只需按照您需要的细节级别,您可以按顺序嵌入逻辑。只允许一个标题,那么段落就可以用一个没有任何标签的文本列表来完成,因为你可以重新创建