我已经输入了XML,并将其转换为clojure-map,可以像这样在一个clojure映射中看到所有值
但是如何从嵌套的detail_D1标签XML结构中过滤某些值(mnAmountReceived)。
我的XML就是这样,为了简洁起见,被截断了:
<svResponse category="EVENT" environment="ENV910" pwd="asdfas"
responseCreator="XAPI" role="ALL" session="7370710" token="asdfasf"
type="realTimeEvent" user="sv"
xmlns:rte="http://www.schemas.e1.oracle.com">
<event>
<header>
<eventVersion>1.0</eventVersion>
<type>EVENTOUT</type>
<user>sv</user>
<role>*ALL</role>
</header>
<body elementCount="3">
<detail_D1>
<szNextStatus>999</szNextStatus>
<mnOrderLineNumber>1.000</mnOrderLineNumber>
<mnAmountReceived>100</mnAmountReceived>
</detail_D1>
<detail_D1>
<szNextStatus>999</szNextStatus>
<mnOrderLineNumber>2.000</mnOrderLineNumber>
<mnAmountReceived>200</mnAmountReceived>
</detail_D1>
<detail_D1>
<szNextStatus>999</szNextStatus>
<mnOrderLineNumber>3.000</mnOrderLineNumber>
<mnAmountReceived>300</mnAmountReceived>
</detail_D1>
</body>
</event>
</svResponse>
例如:我想过滤mnAmountReceived并根据标签下的mnOrderLineNumber将它们分配给单独的键。
我正在获取一个XML,可以使用以下函数将其转换为clojure映射
(xml/parse-str xml-str))
(defn clojurify-xml-map
[clj-xml]
(->> clj-xml
get-body
(map xml->map)
group-and-flattened-source-data))
我正在尝试使用值1.0过滤掉mnOrderLineNumber,例如,这样我就可以获取对应的mnAmountReceived值
(defn filter-price-line [coll]
(filter #(#{1.0} (-> % :mnOrderLineNumber read-string)) coll)
)
我想过滤掉mnAmountReceived并知道它附带了哪个mnOrderLineNumber,以便可以在对下游系统的适当字段的响应中将其映射出来。
答案 0 :(得分:4)
似乎您想解析XML,并且能够将每个detail_D1
视为一个映射,以便可以同时接收行号和金额。如果是这种情况,一种方法可能是使用拉链将数据解析为Clojure数据结构,然后解析为filter
。这是一个示例:
(ns so
(:require [clojure.data.xml :as x]
[clojure.data.zip.xml :as z]
[clojure.zip :as zip]
[clojure.java.io :as io]))
(defn parse
[file]
(letfn [(parse-detail [z]
{:next-status (Integer/parseInt (z/xml1-> z :szNextStatus z/text))
:line-number (Double/parseDouble (z/xml1-> z :mnOrderLineNumber z/text))
:amount-received (Integer/parseInt (z/xml1-> z :mnAmountReceived z/text))})]
(with-open [r (io/reader file)]
(let [zipper (->> r x/parse zip/xml-zip)]
(z/xml-> zipper :svResponse :event :body :detail_D1 parse-detail)))))
(comment
(parse "input.xml") =>
({:next-status 999 :line-number 1.0 :amount-received 100}
{:next-status 999 :line-number 2.0 :amount-received 200}
{:next-status 999 :line-number 3.0 :amount-received 300})
(filter (comp #{1.0} :line-number) (parse "input.xml")) =>
({:next-status 999 :line-number 1.0 :amount-received 100})
)