clojure.data.xml 仅负责 xml 解析与序列化,不处理 http 上传;纯 xml 上传需用 clj-http 发送 emit-str 生成的字符串并设 :content-type :xml;multipart 上传须将 emit-str 结果转为 bytearrayinputstream 流并指定 :filename 和 :content-type。

data.xml 本身不处理 HTTP 上传
这是最常被误解的一点:clojure.data.xml 只负责 XML 的解析(parse-str / parse)和序列化(emit-str / emit),它不涉及网络、文件读写或 multipart 表单组装。所谓“XML 上传”,实际是三步组合:读取原始 XML 数据 → 构建符合服务端要求的 HTTP 请求体(可能是纯 XML body,也可能是 multipart 中的 XML 文件字段)→ 发起 HTTP 请求。
纯 XML body 上传:用 clj-http + data.xml 组合
多数 REST API 接收 Content-Type: application/xml 的纯 XML 请求体。这时你只需用 data.xml/emit-str 生成字符串,再交给 HTTP 客户端:
(require '[clojure.data.xml :as xml]
'[clj-http.client :as http])
(def payload (xml/element :root {}
(xml/element :item {:id "123"} "content")))
(http/post "https://api.example.com/data"
{:body (xml/emit-str payload)
:content-type :xml
:accept :xml})
注意点:
-
emit-str默认不带 XML 声明(<?xml version="1.0"?>),如需声明,加参数:(xml/emit-str payload :encoding "UTF-8" :standalone true) - 确保服务端接受
application/xml;若返回 415 错误,检查:content-type是否拼写为"application/xml"或用:xml关键字(clj-http 支持) - 如果 XML 含中文或特殊字符,
:encoding "UTF-8"必须显式指定,否则 clj-http 可能用平台默认编码发送乱码
multipart XML 文件上传:用 clj-http 的 :multipart
当后端要求以 multipart/form-data 提交 XML(例如作为 file 字段),不能直接传字符串——必须构造 java.io.ByteArrayInputStream 或临时文件流:
网奇.NET网络商城系统是基于.Net平台开发的免费商城系统。功能强大,操作方便,设置简便。无需任何设置,上传到支持asp.net的主机空间即可使用。系统特色功能:1、同时支持Access和SqlServer数据库;2、支持多语言、多模板3、可定制缺货处理功能4、支持附件销售功能5、支持会员组批发功能6、提供页面设计API函数7、支持预付款功能8、配送价格分地区按数学公式计算9、商品支持多类别,可
(require '[clojure.data.xml :as xml]
'[clj-http.client :as http]
'[java.io :as io])
(def xml-data (xml/element :upload {:ts "2024"} "data"))
(http/post "https://api.example.com/upload"
{:multipart [{:name "file"
:content (io/input-stream
(.getBytes (xml/emit-str xml-data) "UTF-8"))
:filename "data.xml"
:content-type "application/xml"}]})
关键细节:
-
:content字段必须是 Java 输入流,不能是字符串或字节数组(clj-http 会拒绝) -
:filename和:content-type在 multipart 场景中常被后端校验,漏掉可能返回 400 - 避免用
FileInputStream指向磁盘文件——这破坏函数式原则;内存流(ByteArrayInputStream)更符合“纯数据转换”逻辑
解析上传响应时的常见陷阱
即使上传成功,响应体仍是 XML,需再次用 data.xml/parse-str 处理。但注意:
- 响应可能含 BOM 或空白前缀,导致
parse-str报org.xml.sax.SAXParseException: Content is not allowed in prolog—— 先用clojure.string/trim清理 - 某些服务返回
text/plain类型的 XML 内容,clj-http 不自动解码,需手动指定:as :string,再传给parse-str - 不要在
parse-str前做正则替换或字符串拼接——XML 结构敏感,应交由解析器处理命名空间、CDATA、实体等
真正麻烦的从来不是生成 XML,而是服务端对格式、编码、命名空间、HTTP 头的隐式要求。每次上传前,用 curl -v 对比真实请求,比读文档更快定位问题。









