Re: SXPath namespaces

"Dmitry Lizorkin" <[email protected]> Fri, 12 May 2006 14:41:30 +0400
Newsgroups gmane.lisp.scheme.ssax-sxml
Message-ID <[email protected]>
Hi,

Please excuse me for the delayed answer to your question.

Since your SXML document contains a namespace-id in element names, a namespace prefix occuring in the XPath node test should be mapped to that namespace-id for obtaining the result we expect, i.e:

((sxpath "my:schema" '[(my . "xsd")])
   doc)
==>
((xsd:schema))

Please note that (unlike XPath 2.0) the XPath 1.0 Specification implemented in sxpath does not support a default namespace declaration in node tests: in subsect. 2.3 of the XPath 1.0 Specification, it is stated that "..if the QName [in the node test] does not have a prefix, then the namespace URI is null (this is the same way attribute names are expanded)." You thus _have to_ use a prefix in an XPath name test for addressing a 
named node from a non-null namespace URI; i.e. your code
(sxpath "schema" '[...])
selects the 'schema child element (from a null namespace) regardless of the namespace binding supplied as the second argument.

Since "XPath is a language for _addressing_ parts of an XML document", the result produced by the `sxpath' function for an XPath location path is a nodeset consisting of nodes in _exactly_ the same form (by `eq?') as in the original SXML document. You thus have no way of converting the '(xsd:schema) element into a '(schema) or '(my:schema) element in pure XPath. If you want your result to be returned in a different form, you can apply queries/transformations to it afterwards. For example, you can remove the "xsd:" prefix from all the nodes in the nodeset by using pre-post-order transformations:

(pre-post-order
   '((xsd:schema))
   `((*text* . ,(lambda (tag text) text))
     (*default*
      . ,(lambda (tag . content)
           (cons
            (if
             (equal?
              (sxml:name->ns-id tag)  ; produces either #f or a string
              "xsd")
             (string->symbol (sxml:ncname
                              (list tag)  ; a node is required as an argument
                              ))
             tag)
            content)))))
==>
((schema))

Note however that new SXML nodes are essentially constructed as a result of such a transformation; these new nodes are physically different from the ones from the original SXML document.

Regards,
Dmitry

  ----- Original Message ----- 
  From: Victor Morilla Padial 
  To: [email protected] 
  Sent: Tuesday, May 09, 2006 1:42 AM
  Subject: [ssax-sxml] SXPath namespaces


  Hi,

  Given the following code:

  (define doc
    '(*TOP*
      (@
       (*NAMESPACES*
        (xsd "http://www.w3.org/2001/XMLSchema")))
      (*PI* xml "version=\"1.0\" encoding=\"UTF-8\"")
      (xsd:schema)))

  (pretty-print ((sxpath "my:schema" '[(my . "http://www.w3.org/2001/XMLSchema")]) doc))
  (pretty-print ((sxpath "schema" '[(#f . "http://www.w3.org/2001/XMLSchema")]) doc))
  (pretty-print ((sxpath "xsd:schema" '[(xsd . "http://www.w3.org/2001/XMLSchema")]) doc))


  I spected the result:
  ((my:schema))
  ((schema))
  ((xsd:schema))

  But the real result is:
  (())
  (())
  (()) 


  What am I doing wrong? What's the correct way to deal with namespaces using SXPath

  Thanks in advance,

  VĂ­ctor Morilla