Как разобрать XML с помощью cxml и stp, содержащих амперсанд

StackOverflow https://stackoverflow.com//questions/12678106

  •  12-12-2019
  •  | 
  •  

Вопрос

Я хочу проанализировать следующий XML-код:

(cxml:parse "<BEGIN><URL>www.some.de/url?some=data&bad=stuff</URL></BEGIN>" (stp:make-builder))

это приводит к

 #<CXML:WELL-FORMEDNESS-VIOLATION "~A" {1003C5E163}>

поскольку '&' - это специальный символ XML.Но если я использую &amp;? вместо этого результатом является:

(cxml:parse "<BEGIN><URL>www.some.de/url?some=data&amp;bad=stuff</URL></BEGIN>" (stp:make-builder))
=>#.(CXML-STP-IMPL::DOCUMENT
   :CHILDREN '(#.(CXML-STP:ELEMENT
                  #| :PARENT of type DOCUMENT |#
                  :CHILDREN '(#.(CXML-STP:ELEMENT
                                 #| :PARENT of type ELEMENT |#
                                 :CHILDREN '(#.(CXML-STP:TEXT
                                                #| :PARENT of type ELEMENT |#
                                                :DATA "www.some.de/url?some=data")
                                             #.(CXML-STP:TEXT
                                                #| :PARENT of type ELEMENT |#
                                                :DATA "&")
                                             #.(CXML-STP:TEXT
                                                #| :PARENT of type ELEMENT |#
                                                :DATA "bad=stuff"))
                                 :LOCAL-NAME "URL"))
                  :LOCAL-NAME "BEGIN")))

Что не совсем то, чего я ожидал, поскольку должен быть только один дочерний элемент CXML-STP:TEXT с ДАННЫМИ "www.some.de/url?some=data&bad=stuff"

Как я могу исправить это неправильное (?) поведение?

Это было полезно?

Решение

Такое поведение, хотя и не очень удобное, на самом деле присутствует и во многих других XML-анализаторах.Вероятно, причина этого заключается в том, чтобы иметь возможность анализировать произвольные XML-объекты и применять к ним некоторые пользовательские правила.Хотя, это может быть просто побочным продуктом реализации синтаксического анализатора.Я пока не мог этого выяснить.

Для варианта синтаксического анализатора SAX я пришел к следующему подходу:

(defclass my-sax (sax:sax-parser-mixin)
  ((title :accessor title :initform nil)
   (tag :accessor tag :initform nil)
   (text :accessor text :initform "")))

(defmethod sax:start-element ((sax my-sax) namespace-uri local-name
                              qname attributes)
  (with-slots (tag tagcount text) sax
              (setf tag local-name
                    text "")))

(defmethod sax:characters ((sax my-sax) data)
  (with-slots (title tag text) sax
    (switch (tag :test 'string=)
      ("text"  (setf text (conatenate 'string text data)))
      ("title" (setf title data)))))

(defmethod sax:end-element ((sax my-sax) namespace-uri local-name qname)
  (with-slots (title tag text) sax
    (when (string= "text" local-name)
      ;; process (text sax)
    )))

Т.е.Я собираю текст в sax:characters и обработать это в sax:end-element.В STP вы, вероятно, можете обойтись еще проще, просто объединив соседние text элементы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top