The handler does not call the parser, but it processes the parsed values. Thus, instead of creating a string containing <bar /> , you should call a method that would be called if <bar /> was actually encountered. In this case, if the document really had
content <bar/> ola
inside the test element, then there would be calls:
(sax:characters handler "content ") (sax:start-element handler nil nil "bar" '()) (sax:end-element handler nil nil "bar" (sax:characters handler " ola")
So all you have to do is split the string by the character | (you can use CL-PPCRE to do this if you want, although there may be easier solutions) and then make a next-method call for each part of the line and calls sax: start-element and sax: end-element between:
(defmethod sax:characters ((handler preproc) data) (let ((parts (cl-ppcre:split "\\|" data))) ;; check this on edge cases, though, eg, "", "|", "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>"
source share