如何用最新版org.clojure/data.xml生成无命名空间XML?
解决org.clojure/data.xml预览版生成Atom Feed的命名空间问题
问题背景
在使用org.clojure/data.xml生成符合Atom规范的Feed时,新旧版本的表现差异导致了兼容性问题:
- 稳定版0.0.8:执行以下代码
能生成符合要求的无命名空间前缀XML:(xml/emit-str (xml/sexp-as-element [:feed {:xmlns "http://www.w3.org/2005/Atom"}]))<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"/> - 预览版0.2.0-alpha6:同样的代码会自动添加
:a命名空间前缀,不符合Atom的无命名空间要求:<?xml version="1.0" encoding="UTF-8"?><feed xmlns:a="http://www.w3.org/2005/Atom"/>
尝试相关方案后,生成的XML仍被Atom验证器拒绝:
执行代码:
(xml/emit-str (xml/sexp-as-element [::atom/feed {:xmlns "http://www.w3.org/2005/Atom"} [:title "Some site title"]]))
生成的结果中<title>元素出现多余的空命名空间声明,导致验证失败:
<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title xmlns="" xmlns:a="http://www.w3.org/2005/Atom">Some site title</title></feed>
解决方案
要让预览版生成符合Atom规范的XML,需要确保根元素的命名空间成为默认命名空间,且所有子元素自动继承该命名空间,避免多余的前缀或空命名空间声明。具体步骤如下:
定义默认命名空间实例
直接创建Namespace实例,将前缀设为nil,强制把Atom命名空间设为默认:(require '[clojure.data.xml :as xml]) (import '[clojure.data.xml Namespace]) (def atom-default-ns (Namespace. nil "http://www.w3.org/2005/Atom"))构造归属默认命名空间的元素
使用xml/element构造所有Atom元素,确保它们都归属到默认命名空间:(defn valid-atom-feed [] (xml/element atom-default-ns "feed" {} (xml/element atom-default-ns "title" {} "Some site title") (xml/element atom-default-ns "updated" {} "2024-05-20T14:30:00Z") (xml/element atom-default-ns "id" {} "urn:uuid:12345678-1234-5678-1234-567812345678") ;; 添加其他Atom必填元素 )) (xml/emit-str (valid-atom-feed))生成的符合规范的XML
最终输出的XML完全符合Atom验证要求:<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Some site title</title><updated>2024-05-20T14:30:00Z</updated><id>urn:uuid:12345678-1234-5678-1234-567812345678</id></feed>
原理说明
预览版的data.xml对命名空间的处理逻辑更严谨,默认会为显式声明的命名空间分配前缀。通过创建带nil前缀的Namespace实例,我们直接将Atom命名空间设为文档的默认命名空间,所有子元素归属该命名空间后,就不会出现多余的空命名空间或前缀声明,完美适配Atom Feed的验证规则。
内容的提问来源于stack exchange,提问作者Alain M. Lafon
相关产品推荐
相关产品推荐

