clojure名称空间感知xml解析器/ zipper

too*_*kit 3 xml soap clojure

有谁知道一个名称空间感知的xml解析器/ zipper?

我不想拉入一大堆轴或类似的库,而是希望解析以下内容:

(ns foo
  (:require [clojure.zip :as zip]
            [clojure.xml :as xml])
  (:use clojure.data.zip.xml))

(def xml "<soap:Envelope xmlns=\"urn:WEBSERVICE-URN\"
                         xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"
                         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">
            <soap:Body>
              <loginResponse>
                 <result>           
                    <sessionKey>SESSION-KEY-HERE</sessionKey>
                 </result>
              </loginResponse>
            </soap:Body>
           </soap:Envelope>")

(def root 
  (zip/xml-zip 
    (xml/parse 
      (java.io.ByteArrayInputStream. (.getBytes xml "UTF-8")))))

(def key (xml1-> root ???? ???? :loginResponse :result :sessionKey text))
Run Code Online (Sandbox Code Playgroud)

我似乎无法导航具有XML命名空间的xml元素?

Ale*_*lex 5

I think your problem here might be your use of xml1-> and not the namespaces in the XML. The tag= predicate in the XML zip namespace (which is implied when using keywords with xml1->) defaults to auto-descent mode, meaning that it descends to the children of the current node before trying to match element tags. Since the root element is already a soap:Envelope, you don't need to include that filter in the list with xml1->. The following should give you what you're looking for:

(xml1-> root :soap:Body :loginResponse :result :sessionKey text)
Run Code Online (Sandbox Code Playgroud)

Note that element qnames are used in their unexpanded form as tag names in clojure.xml, and it's perfectly fine to have a keyword whose name contains a colon.

Alternatively, you could say:

(require '[clojure.data.zip :as zf])
(xml1-> (zf/auto false root)
        :soap:Envelope :soap:Body :loginResponse :result :sessionKey text)
Run Code Online (Sandbox Code Playgroud)

如果您仍然需要一个名称空间感知的XML解析器,那么data.xml中就有一个,尽管它只是丢弃名称空间声明并仅使用本地名称:

(require '[clojure.data.xml :as data-xml])
(def root (-> (java.io.StringReader. xml) data-xml/parse zip/xml-zip)
(xml1-> root :Body :loginResponse :result :sessionKey text)
Run Code Online (Sandbox Code Playgroud)