Clojure XML Parsing

后端 未结 2 2036
忘了有多久
忘了有多久 2020-12-22 16:40

I can not find any info on how to parse xml documents and access elements.

I have found two ways to parse the xml document

(clojure.zip/xml-zip (cloj         


        
相关标签:
2条回答
  • 2020-12-22 17:23

    Suppose you have the following xml to parse in your file:

    <high-node>
       <low-node>my text</low-node>
    </high-node>
    

    you load clojure.xml:

    user=> (use 'clojure.xml)
    

    when parsed, the xml will have the following structure:

    {:tag :high-node, :attrs nil, :content [{:tag :low-node, :attrs nil, :content ["my text"]}]}
    

    and then you can seq over the content of the file to get the content of the low-node:

    user=> (for [x (xml-seq 
                  (parse (java.io.File. file)))
                     :when (= :low-node (:tag x))]
             (first (:content x)))
    
    ("my text")
    

    Similarly, if you wanted to have access to the entire list of information on low-node, you would change the :when predicate to (= (:high-node (:tag x))):

    user=> (for [x (xml-seq 
                  (parse (java.io.File. file)))
                     :when (= :high-node (:tag x))]
             (first (:content x)))
    
    ({:tag :low-node, :attrs nil, :content ["my text"]})
    

    This works because the keywords can operate as functions. See Questions about lists and other stuff in Clojure and Data Structures: Keywords

    0 讨论(0)
  • 2020-12-22 17:47

    The above answer works, but I find it a lot easier to use clojure.data.zip.xml (used to be clojure-contrib.zip-filter.xml prior to Clojure 1.3).

    file:

    myfile.xml:

    <songs>
      <track id="t1"><name>Track one</name></track>
      <track id="t2"><name>Track two</name></track>
    </songs>
    

    code:

    ; Clojure 1.3
    (ns example
      (:use [clojure.data.zip.xml :only (attr text xml->)]) ; dep: see below
      (:require [clojure.xml :as xml]
                [clojure.zip :as zip]))
    
    (def xml (xml/parse "myfile.xml"))
    (def zipped (zip/xml-zip xml))
    (xml-> zipped :track :name text)       ; ("Track one" "Track two")
    (xml-> zipped :track (attr :id))       ; ("t1" "t2")
    

    Unfortunately, you need to pull in a dependency on data.zip to get this nice read/filter functionality. It's worth the dependency :) In lein it would be (as of 17-Aug-2013):

    [org.clojure/data.zip "0.1.1"]
    

    And as for docs for data.zip.xml ... I just look at the relatively small source file here to see what is possible. Another good SO answer here, too.

    0 讨论(0)
提交回复
热议问题