       :enclosedCharacter
       :er
       :cursive
-      :image ;; Inline tag (Emoji).
-      :noteBodyInline ;; Inline tag.
-      :noteMarker ;; Inline tag.
+      :image                                                ;; Inline tag (Emoji).
+      :noteBodyInline                                       ;; Inline tag.
+      :noteMarker                                           ;; Inline tag.
       :superScript
       :subScript
       :fraction

                      :_ #_"小説の主人公あるいは語り手の人称(T)"
                      :_ #_"小説の主人公あるいは語り手の人称(N)"

                      :protagonist-personal-pronoun #_"小説の主人公あるいは語り手の人称"
                      :other-addressing #_"小説以外の文章の内容"]
              #_(->> bccwj-meta-annotation-data
                     first
                     rest)]
          (r/fold
           (r/monoid
            (fn [a [basename & record]]
              (assoc a basename
                     (for-map [[k v] (zipmap header record)
                               :when (not= k :_)]
                         k (cond (empty? v) nil

                                 ;; Coerce into Likert-scale Longs.
                                 (and (#{:target-audience :hard-soft :informality :addressing :other-addressing} k)
                                      (re-seq #"^\d+" v))
                                 (Long/parseLong v)

                                 ;; Coerce into binary values.
                                 (#{:forward-or-afterward :dialog
                                     :quotation-type :visual
                                     :db-or-list :archaic
                                     :foreign-language :math-or-code
                                     :legalese :questionable-content
                                     :low-content} k)
                                 (case (subs v 0 1) "1" true "0" false true)

                                 :else v))))
            (fn [] {}))
           (next bccwj-meta-annotation-data)))]

    (->> (merge-with merge bccwj-metadata bccwj-annotations)
         (map-vals (fn [vs] (into {} (r/remove #(nil? (val %)) vs))))
         vals)))

(comment
  (pprint (take 10 (map (comp :category :metadata) (filter #(= ((comp :subcorpus :metadata) %) "PM") (document-seq "/data/BCCWJ-2012-dvd1/DOC/" "/data/BCCWJ-2012-dvd1/C-XML/VARIABLE/")))))
  (def cats (into #{} (map (comp :category :metadata) (document-seq "/data/BCCWJ-2012-dvd1/DOC/" "/data/BCCWJ-2012-dvd1/C-XML/VARIABLE/"))))
  (def c-topics (into #{} (map :topic (mapcat (comp #(remove empty? %) #(filter map? %)) cats))))
  (def c-audiences (into #{} (map :audience (mapcat (comp #(remove empty? %) #(filter map? %)) cats))))
  (def c-medias (into #{} (map :media (mapcat (comp #(remove empty? %) #(filter map? %)) cats))))
  (def ndc-topics (into #{} (mapcat (comp #(remove empty? %) #(remove map? %)) cats)))
  (clojure.set/intersection c-topics ndc-topics)
  ;; How to merge these intersecting labels that are recorded at different levels?
  #{"情報科学" "宗教" "商業" "旅行" "物理学" "総記" "仏教" "キリスト教" "化学" "機械" "哲学" "ドイツ語" "家事" "法律" "数学" "日本語" "教育" "伝記" "社会" "生物学" "水産業"}
)

(s/defn parse-document :- SentencesSchema
  [filename :- s/Str]
  (->> filename
       io/input-stream
       xml/parse
       walk-and-emit
       (map #(hash-map ; Remove nils/empty strings from :tags and :sentences.
              :tags (into #{} (r/filter identity (:tags %)))
              :sentences (into [] (r/remove empty? (:sentences %)))))
       (remove #(empty? (:sentences %))) ; Remove paragraphs with no sentences.
       vec))

(s/defn document-seq :- [DocumentSchema] ;; TODO validate lazy-seq?
  [options :- {:corpus-dir s/Str
               :metadata-dir s/Str
               s/Keyword s/Any}]
  (lazy-seq
   (->> (parse-metadata (:metadata-dir options))
        (map (fn [metadata]
               (let [filename (str (:corpus-dir options) (:subcorpus metadata) "/" (:basename metadata) ".xml")]
                 {:metadata metadata
                  :paragraphs (parse-document filename)}))))))

(comment
  (s/with-fn-validation
   (take 10 (map (comp :category :metadata) (document-seq "/data/BCCWJ-2012-dvd1/DOC/" "/data/BCCWJ-2012-dvd1/C-XML/VARIABLE/")))))

      (fz/root par-loc)
      (let [xml-node (fz/node xml-loc)
            tag (:tag xml-node)
            xml-loc-down (and (fz/branch? xml-loc) (fz/down xml-loc))
            xml-loc-right (and (not xml-loc-down) (fz/right xml-loc))
            xml-loc-up (and (not xml-loc-down) (not xml-loc-right) (backtrack-with-distance xml-loc)) ; At lowest depth for this paragraph.
            next-direction (cond xml-loc-down :down
                                 xml-loc-right :same
                                 :else (:depth xml-loc-up))
