Question

Je souhaite analyser le code XML suivant :

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

cela se traduit par

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

car '&' est un caractère spécial XML.Mais si j'utilise &amp;? au lieu de cela, le résultat est :

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

Ce qui n'est pas exactement ce à quoi je m'attendais car il ne devrait y avoir qu'un seul enfant CXML-STP:TEXT avec DATA "www.some.de/url?some=data&bad=stuff"

Comment puis-je corriger ce mauvais (?) comportement ?

Était-ce utile?

La solution

Ce comportement, bien que peu pratique, est en fait également présent dans de nombreux autres analyseurs XML.La raison en est probablement la possibilité d'analyser des entités XML arbitraires et de leur appliquer certaines règles définies par l'utilisateur.Bien que cela puisse être simplement un sous-produit de l’implémentation de l’analyseur.Je n'ai pas encore pu le savoir.

Pour la variante SAX de l'analyseur, je suis arrivé à l'approche suivante :

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

C'est à dire.Je rassemble le texte dans sax:characters et traitez-le dans sax:end-element.Dans STP, vous pouvez probablement vous en sortir encore plus facilement en concaténant simplement les fichiers voisins. text éléments.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top