我需要将一个大XML文件的所有文本块中的所有字符|转换为标记。也就是说,每当我发现
<test att="one|two">content | something more | and done</test>我需要转变为
<test att="one|two">content <bar/> something more <bar/> and done</test>请注意,|也可以出现在属性值中,在这种情况下,它们必须保持不变。在阅读了CXML焦点中的SAX概述部分的Transforming幻灯片后,我写道
(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>"有什么想法或方向吗?
发布于 2014-11-03 22:01:55
处理程序不调用解析器,但正在处理已解析的值。因此,您要做的不是构造一个包含的字符串,而是调用如果实际遇到就会调用的方法。在这种情况下,如果文档实际上有
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-来实现这一点,尽管可能有更轻量级的解决方案),然后为每个字符串部分执行一个call-next-method,并在其间调用sax:start-element和sax:end-element:
(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>"https://stackoverflow.com/questions/26714660
复制相似问题