4

私はclojureを初めて使用し、enliveを使用してhtmlドキュメントのテキストノードを変換してきました。私の最終目標は、構造をhtml、タグ、その他すべてに変換することです。

現在、enlive-html / html-resourceによって返された構造マップを取得し、それを使用してhtmlに変換することができます。

(apply str (html/emit* nodes))

ここで、nodesは構造マップです。

必要に応じて、structmapの:contentテキストノードを変換することもできます。ただし、structmapのコンテンツテキストノードを変換した後、MapEntriesのlazyseqになります。これを構造マップに変換して戻したいので、emit*を使用できます。lazyseqsとstructmapsがネストされているため、これは少し注意が必要です。

tldr:

変換するにはどうすればよいですか:

([:tag :html]
 [:attrs nil]
 [:content
  ("\n"
   ([:tag :head]
    [:attrs nil]
    [:content
     ("\n  "
      ([:tag :title] [:attrs nil] [:content ("Page Title")])
      "  \n")])
   "\n"
   ([:tag :body]
    [:attrs nil]
    [:content
     ("\n  "
      ([:tag :div]
       [:attrs {:id "wrap"}]
       [:content
        ("\n    "
         ([:tag :h1] [:attrs nil] [:content ("header")])
         "\n    "
         ([:tag :p] [:attrs nil] [:content ("some paragrah text")])
         "\n  ")])
      "\n")])
   "\n\n")])

の中へ:

    {:tag :html,
 :attrs nil,
 :content
 ("\n"
  {:tag :head,
   :attrs nil,
   :content
   ("\n  " {:tag :title, :attrs nil, :content ("Page Title")} "  \n")}
  "\n"
  {:tag :body,
   :attrs nil,
   :content
   ("\n  "
    {:tag :div,
     :attrs {:id "wrap"},
     :content
     ("\n    "
      {:tag :h1, :attrs nil, :content ("header")}
      "\n    "
      {:tag :p, :attrs nil, :content ("some paragrah text")}
      "\n  ")}
    "\n")}
  "\n\n")}

アップデート

kotarakの応答は、の方向を示していましたupdate-in。これを使用して、マップをシーケンスに変換せずに所定の位置に変更することができたため、質問は無関係になりました。

(defn modify-or-go-deeper
  "If item is a map, updates its content, else if it's a string, modifies it"
  [item]
  (declare update-content)
  (cond
    (map? item) (update-content item)
    (string? item) (modify-text item)))

(defn update-content
  "Calls modify-or-go-deeper on each element of the :content sequence"
  [coll]
  (update-in coll [:content] (partial map modify-or-go-deeper)))

for以前は地図で使っていましたupdate-inが、行く方法です。

4

2 に答える 2

4

すべてをマップに戻し、コンテンツを再帰的にウォークします。

(defn into-xml
  [coll]
  (let [tag (into {} coll)]
    (update-in tag [:content] (partial map into-xml))))

コンテンツは、アクセスしたときにのみ変換されることに注意してください。

編集:うわー、文字列の部分を逃した。ここで動作するバージョン:

(defn into-xml
  [coll]
  (if-not (string? coll)
    (let [tag (into {} coll)]
      (update-in tag [:content] (partial map into-xml)))
    coll))
于 2012-06-14T06:01:43.460 に答える
1

試す

(def mp '([:tag :html] [:attrs nil] [:content
    (""
    ([:tag :head] [:attrs nil] [:content
        ("\n\t\t"
        ([:tag :title] [:attrs nil] [:content ("page title")])
        "\n\t\t")])
        "\n\t"
        ([:tag :body] [:attrs nil] [:content
            ("\n\t\t"
            ([:tag :div] [:attrs {:id "wrapper"}] [:content
            ("\n\t\t  "
            ([:tag :h1] [:attrs nil] [:content
                ("\n  \t\t\tpage title"
                ([:tag :br] [:attrs nil] [:content ()])
                "\n  \t\t\tand more title\n  \t\t")])
                "\n  \t\t"
                ([:tag :p] [:attrs nil] [:content
                    ("\n  \t\tSome paragraph text"
                    ([:tag :img] [:attrs {:src "images/image.png", :id "image"}] [:content nil])
                    "\n  \t\t")])
            "\n\t\t")]
            "\n\t     \n\t\t"))]
        "\n\n"))]))

(clojure.walk/postwalk (fn [x]
                         (if (and (list? x) (vector? (first x)))
                           (into {} x)
                           x))
                       mp)

エラーがスローされますが、入力をに変更すると

([:tag :html]
 [:attrs nil]
 [:content
  (""
   ([:tag :head]
    [:attrs nil]
    [:content
     ("\n\t\t"
      ([:tag :title] [:attrs nil] [:content ("page title")])
      "\n\t\t")])
   "\n\t"
   ([:tag :body]
    [:attrs nil]
    [:content
     ("\n\t\t"
      ([:tag :div]
       [:attrs {:id "wrapper"}]
       [:content
        ("\n\t\t  "
         ([:tag :h1]
          [:attrs nil]
          [:content
           ("\n  \t\t\tpage title"
            ([:tag :br] [:attrs nil] [:content ()])
            "\n  \t\t\tand more title\n  \t\t")])
         "\n  \t\t"
         ([:tag :p]
          [:attrs nil]
          [:content
           ("\n  \t\tSome paragraph text"
            ([:tag :img]
             [:attrs {:src "images/image.png", :id "image"}]
             [:content nil])
            "\n  \t\t")])
         "\n\t\t")]
       ))]))]))

その後、それは大丈夫です。違いは、編集された入力で、キーと値のペアを含む同じリストから「\ n \ t\t」のような文字列を削除することです。お役に立てれば。

編集: 以下は私のために働いた:

(def mp '([:tag :html]
 [:attrs nil]
 [:content
  (""
   ([:tag :head]
    [:attrs nil]
    [:content
     ("\n\t\t"
      ([:tag :title] [:attrs nil] [:content ("page title")])
      "\n\t\t")])
   "\n\t"
   ([:tag :body]
    [:attrs nil]
    [:content
     ("\n\t\t"
      ([:tag :div]
       [:attrs {:id "wrapper"}]
       [:content
        ("\n\t\t  "
         ([:tag :h1]
          [:attrs nil]
          [:content
           ("\n  \t\t\tpage title"
            ([:tag :br] [:attrs nil] [:content ()])
            "\n  \t\t\tand more title\n  \t\t")])
         "\n  \t\t"
         ([:tag :p]
          [:attrs nil]
          [:content
           ("\n  \t\tSome paragraph text"
            ([:tag :img]
             [:attrs {:src "images/image.png", :id "image"}]
             [:content nil])
            "\n  \t\t")])
         "\n\t\t")]
       ))]))]))

(clojure.walk/postwalk (fn [x]
                         (if (and (list? x) (vector? (first x)))
                           (into {} x)
                           x))
                       mp)

コピーして、replに貼り付けてみてください。次のものを取得する必要があります。

{:tag :html,
 :attrs nil,
 :content
 (""
  {:tag :head,
   :attrs nil,
   :content
   ("\n\t\t"
    {:tag :title, :attrs nil, :content ("page title")}
    "\n\t\t")}
  "\n\t"
  {:tag :body,
   :attrs nil,
   :content
   ("\n\t\t"
    {:tag :div,
     :attrs {:id "wrapper"},
     :content
     ("\n\t\t  "
      {:tag :h1,
       :attrs nil,
       :content
       ("\n  \t\t\tpage title"
        {:tag :br, :attrs nil, :content ()}
        "\n  \t\t\tand more title\n  \t\t")}
      "\n  \t\t"
      {:tag :p,
       :attrs nil,
       :content
       ("\n  \t\tSome paragraph text"
        {:tag :img,
         :attrs {:src "images/image.png", :id "image"},
         :content nil}
        "\n  \t\t")}
      "\n\t\t")})})}
于 2012-06-13T23:29:25.233 に答える