我需要改造所有字符| 在一个大的XML文件中的所有文本块标记。 也就是说,只要我发现
<test att="one|two">content | something more | and done</test>
我需要转换到
<test att="one|two">content <bar/> something more <bar/> and done</test>
需要注意的是| 也可以发生在属性值,在这种情况下,他们必须依然古色古香不变。 看完后转化的CXML focumentation的SAX概述部分的幻灯片,我写的
(defclass preproc (cxml:sax-proxy) ())
(defmethod sax:characters ((handler preproc) data)
(call-next-method handler (cl-ppcre:regex-replace "\\|" data "<bar/>")))
但是,当然,它产生一个字符串(逃脱)没有在最后的XML标签。
WML> (cxml:parse "<test>content | ola</test>"
(make-instance 'preproc
:chained-handler (cxml:make-string-sink)))
<?xml version="1.0" encoding="UTF-8"?>
<test>content <bar/> ola</test>"
任何想法或方向?
该处理程序不调用分析器,但处理已经被解析的值。 因此,而不是构建一个包含字符串 <酒吧/>,你想要做的是调用,将如果<酒吧/>实际上已经遇到了已调用的方法。 在这种情况下,如果文档实际上有
content <bar/> ola
测试元件内部的话,那就一直是呼吁:
(sax:characters handler "content ")
(sax:start-element handler nil nil "bar" '())
(sax:end-element handler nil nil "bar"
(sax:characters handler " ola")
所以,你需要做的是在分割字符串| 字符(你可以使用CL-PPCRE对于这一点,如果你想,虽然可能有更多的轻量化解决方案),然后做每串部分呼叫下一个方法 ,并做呼叫萨克斯:开始元素和萨克斯:结束-元素之间:
(defmethod sax:characters ((handler preproc) data)
(let ((parts (cl-ppcre:split "\\|" data)))
;; check this on edge cases, though, e.g., "", "|", "a|", strings
;; without any "|", etc.
(call-next-method handler (pop parts))
(dolist (part parts)
(sax:start-element handler nil nil "bar" '())
(sax:end-element handler nil nil "bar")
(call-next-method handler part))))
(cxml:parse "<test>content | ola</test>"
(make-instance 'preproc
:chained-handler (cxml:make-string-sink)))
;=>
; "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
; <test>content <bar/> ola</test>"