Pregunta

Quiero analizar el siguiente código XML:

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

esto resulta en

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

ya que '&' es un carácter especial XML.Pero si uso &amp;? en cambio el resultado es:

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

Lo cual no es exactamente lo que esperaba, ya que solo debería haber un elemento secundario CXML-STP:TEXT con DATOS "www.some.de/url?some=data&bad=stuff"

¿Cómo puedo solucionar este comportamiento incorrecto (?)?

¿Fue útil?

Solución

Este comportamiento, aunque no es muy conveniente, en realidad también está presente en muchos otros analizadores XML.Probablemente la razón es poder analizar entidades XML arbitrarias y aplicarles algunas reglas definidas por el usuario.Aunque puede ser sólo un subproducto de la implementación del analizador.No pude averiguarlo todavía.

Para la variante SAX del analizador llegué al siguiente enfoque:

(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)
    )))

Es decir.Recojo el texto en sax:characters y procesarlo en sax:end-element.En STP, probablemente puedas salir aún más fácilmente concatenando text elementos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top