如何注入元素融入到角色内容用封XML?(How to inject elements into ch

2019-10-21 05:05发布

我需要改造所有字符| 在一个大的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 &lt;bar/&gt; ola</test>"

任何想法或方向?

Answer 1:

该处理程序不调用分析器,但处理已经被解析的值。 因此,而不是构建一个包含字符串 <酒吧/>,你想要做的是调用,将如果<酒吧/>实际上已经遇到了已调用的方法。 在这种情况下,如果文档实际上有

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>"


文章来源: How to inject elements into character content with Closure XML?