I'm using cxml-stp to build XML responses for a web service that implements Microsoft's "Research" API (actually, this is just a generalised search interface). While building this, I found something that looks like a bug in cxml-stp. If this is _not_ a bug, I'd be happy for any hint about what I'm doing wrong :-)
The attachment contains a small test case which builds an XML document and serializes it. The attachment should be compiled and loaded after cxml-stp has been loaded, and the commented-out test form at the end of the file should then be evaluated.
The test uses two implementations of cxml-stp-impl::collect-local-namespaces. With the original implementation, the "Status" and "Providers" elements get incorrect xmlns attributes. With the modified version, this is not the case.
On Tue, May 22, 2012 at 10:43:27AM +0200, Raymond Wiker wrote:
I'm using cxml-stp to build XML responses for a web service that implements Microsoft's "Research" API (actually, this is just a generalised search interface). While building this, I found something that looks like a bug in cxml-stp. If this is _not_ a bug, I'd be happy for any hint about what I'm doing wrong :-)
The attachment contains a small test case which builds an XML document and serializes it. The attachment should be compiled and loaded after cxml-stp has been loaded, and the commented-out test form at the end of the file should then be evaluated.
The test uses two implementations of cxml-stp-impl::collect-local-namespaces. With the original implementation, the "Status" and "Providers" elements get incorrect xmlns attributes. With the modified version, this is not the case.
Sorry, I don't have much time to investigate your example, but I think your "fixup" is wrong. Your code (add-element ...) will put the new element into the namespace with namespace name "", but your "fixup" will emit xml that puts the element into the _default_ namespace (which, in your example will be "urn:Microsoft.Search.Registration.Response"). A namespace of "" is _not_ the same as no declaration.
HTH Ralf Mattes
On May 22, 2012, at 12:16 , rm@tuxteam.de wrote:
On Tue, May 22, 2012 at 10:43:27AM +0200, Raymond Wiker wrote:
I'm using cxml-stp to build XML responses for a web service that implements Microsoft's "Research" API (actually, this is just a generalised search interface). While building this, I found something that looks like a bug in cxml-stp. If this is _not_ a bug, I'd be happy for any hint about what I'm doing wrong :-)
The attachment contains a small test case which builds an XML document and serializes it. The attachment should be compiled and loaded after cxml-stp has been loaded, and the commented-out test form at the end of the file should then be evaluated.
The test uses two implementations of cxml-stp-impl::collect-local-namespaces. With the original implementation, the "Status" and "Providers" elements get incorrect xmlns attributes. With the modified version, this is not the case.
Sorry, I don't have much time to investigate your example, but I think your "fixup" is wrong. Your code (add-element ...) will put the new element into the namespace with namespace name "", but your "fixup" will emit xml that puts the element into the _default_ namespace (which, in your example will be "urn:Microsoft.Search.Registration.Response"). A namespace of "" is _not_ the same as no declaration.
add-element calls cxml-stp:make-element, which sets the namespace to "" if it is not supplied (or nil). Thus, setting namespace-uri to "" if no uri is supplied should not make any difference (and it does not seem to do so - I just checked by defaulting namespace-uri to nil instead of "").
On Tue, May 22, 2012 at 12:03:40PM +0200, Raymond Wiker wrote:
On May 22, 2012, at 12:16 , rm@tuxteam.de wrote:
On Tue, May 22, 2012 at 10:43:27AM +0200, Raymond Wiker wrote:
I'm using cxml-stp to build XML responses for a web service that implements Microsoft's "Research" API (actually, this is just a generalised search interface). While building this, I found something that looks like a bug in cxml-stp. If this is _not_ a bug, I'd be happy for any hint about what I'm doing wrong :-)
The attachment contains a small test case which builds an XML document and serializes it. The attachment should be compiled and loaded after cxml-stp has been loaded, and the commented-out test form at the end of the file should then be evaluated.
The test uses two implementations of cxml-stp-impl::collect-local-namespaces. With the original implementation, the "Status" and "Providers" elements get incorrect xmlns attributes. With the modified version, this is not the case.
Sorry, I don't have much time to investigate your example, but I think your "fixup" is wrong. Your code (add-element ...) will put the new element into the namespace with namespace name "", but your "fixup" will emit xml that puts the element into the _default_ namespace (which, in your example will be "urn:Microsoft.Search.Registration.Response"). A namespace of "" is _not_ the same as no declaration.
add-element calls cxml-stp:make-element, which sets the namespace to "" if it is not supplied (or nil). Thus, setting namespace-uri to "" if no uri is supplied should not make any difference (and it does not seem to do so - I just checked by defaulting namespace-uri to nil instead of "").
Yes, that first observation seemsa to be correct. But the conclusion isn't. Cxml-stp's assumption seems to be that an unspecified namespace means the namespace with uri "" (wich is a valid assumption given that every element/attribute _has_ to be in a namespace). What you seem to expect is that cxml-stp puts an element with unspecified namespace uri into the same namespace as an ancessor element somewhere up the tree whose namespace prefix is "". But the element hierarchy isn't even given during (cxml-stp:make-element ...). Iff you want "Status" to be in the "urn:Microsoft.Search.Registration.Response" namespace, then put it there. Something like:
(let ((namespace-uri "urn:Microsoft.Search.Registration.Response")) (let ((root (cxml-stp:make-element "ProviderUpdate" namespace-uri))) (add-element root `("Status" ,namespace-uri) nil "SUCCESS") ......
will do.
Cheers, RalfD
On Tue, May 22, 2012 at 2:45 PM, rm@tuxteam.de wrote:
On Tue, May 22, 2012 at 12:03:40PM +0200, Raymond Wiker wrote:
On May 22, 2012, at 12:16 , rm@tuxteam.de wrote:
On Tue, May 22, 2012 at 10:43:27AM +0200, Raymond Wiker wrote:
I'm using cxml-stp to build XML responses for a web service that
implements Microsoft's "Research" API (actually, this is just a generalised search interface). While building this, I found something that looks like a bug in cxml-stp. If this is _not_ a bug, I'd be happy for any hint about what I'm doing wrong :-)
The attachment contains a small test case which builds an XML
document and serializes it. The attachment should be compiled and loaded after cxml-stp has been loaded, and the commented-out test form at the end of the file should then be evaluated.
The test uses two implementations of
cxml-stp-impl::collect-local-namespaces. With the original implementation, the "Status" and "Providers" elements get incorrect xmlns attributes. With the modified version, this is not the case.
Sorry, I don't have much time to investigate your example, but I think your "fixup" is wrong. Your code (add-element ...) will put the new element into the namespace with namespace name "", but your "fixup"
will
emit xml that puts the element into the _default_ namespace (which, in your example will be "urn:Microsoft.Search.Registration.Response"). A namespace of "" is _not_ the same as no declaration.
add-element calls cxml-stp:make-element, which sets the namespace to ""
if it is not supplied (or nil). Thus, setting namespace-uri to "" if no uri is supplied should not make any difference (and it does not seem to do so - I just checked by defaulting namespace-uri to nil instead of "").
Yes, that first observation seemsa to be correct. But the conclusion isn't. Cxml-stp's assumption seems to be that an unspecified namespace means the namespace with uri "" (wich is a valid assumption given that every element/attribute _has_ to be in a namespace). What you seem to expect is that cxml-stp puts an element with unspecified namespace uri into the same namespace as an ancessor element somewhere up the tree whose namespace prefix is "". But the element hierarchy isn't even given during (cxml-stp:make-element ...). Iff you want "Status" to be in the "urn:Microsoft.Search.Registration.Response" namespace, then put it there. Something like:
(let ((namespace-uri "urn:Microsoft.Search.Registration.Response")) (let ((root (cxml-stp:make-element "ProviderUpdate" namespace-uri))) (add-element root `("Status" ,namespace-uri) nil "SUCCESS") ......
Aha... thanks.
I was confused about empty namespace uris vs empty namespace tags - I wanted to create nodes that would be in the same namespace as their parent, but I now see why that would be problematic.
Thank you for your patience.
Quoting Raymond Wiker (rwiker@gmail.com):
I was confused about empty namespace uris vs empty namespace tags - I wanted to create nodes that would be in the same namespace as their parent, but I now see why that would be problematic.
Thank you for your patience.
So STP doesn't have a built-in feature for this, but I suppose a helper function could be nice for this purpose. Maybe something like this:
CL-USER> (defun make-element-in-context (qname context) (stp:make-element qname (stp:find-namespace (cxml::split-qname qname) context))) MAKE-ELEMENT-IN-CONTEXT
CL-USER> (stp:make-element "test" "http://bar") #.(CXML-STP:ELEMENT :LOCAL-NAME "test" :NAMESPACE-URI "http://bar")
CL-USER> (make-element-in-context "child" *) #.(CXML-STP:ELEMENT :LOCAL-NAME "child" :NAMESPACE-URI "http://bar")
d.
On Tue, May 22, 2012 at 03:35:30PM +0200, David Lichteblau wrote:
Quoting Raymond Wiker (rwiker@gmail.com):
I was confused about empty namespace uris vs empty namespace tags - I wanted to create nodes that would be in the same namespace as their parent, but I now see why that would be problematic.
Thank you for your patience.
So STP doesn't have a built-in feature for this, but I suppose a helper function could be nice for this purpose. Maybe something like this:
CL-USER> (defun make-element-in-context (qname context) (stp:make-element qname (stp:find-namespace (cxml::split-qname qname) context))) MAKE-ELEMENT-IN-CONTEXT
CL-USER> (stp:make-element "test" "http://bar") #.(CXML-STP:ELEMENT :LOCAL-NAME "test" :NAMESPACE-URI "http://bar")
CL-USER> (make-element-in-context "child" *) #.(CXML-STP:ELEMENT :LOCAL-NAME "child" :NAMESPACE-URI "http://bar")
Well, since the OP already uses a wrapper function to add elements this isn't neccessary. And I think the underlying confusion came from the (wrong) assumption that an empty namespace (i.e. ns-uri = "") would mean "same ns as parent". That's a rather common misconception stemming from the difference between the xml data model and it's serialisaton. Namespace prefixes belong to the later. BTW: why are you using split-qname in your wrapper? Would you expect to feed "foo:bar" to make-element-in-context?
Cheers, RalfD
d.
On May 22, 2012, at 16:46 , rm@tuxteam.de wrote:
On Tue, May 22, 2012 at 03:35:30PM +0200, David Lichteblau wrote:
Quoting Raymond Wiker (rwiker@gmail.com):
I was confused about empty namespace uris vs empty namespace tags - I wanted to create nodes that would be in the same namespace as their parent, but I now see why that would be problematic.
Thank you for your patience.
So STP doesn't have a built-in feature for this, but I suppose a helper function could be nice for this purpose. Maybe something like this:
CL-USER> (defun make-element-in-context (qname context) (stp:make-element qname (stp:find-namespace (cxml::split-qname qname) context))) MAKE-ELEMENT-IN-CONTEXT
CL-USER> (stp:make-element "test" "http://bar") #.(CXML-STP:ELEMENT :LOCAL-NAME "test" :NAMESPACE-URI "http://bar")
CL-USER> (make-element-in-context "child" *) #.(CXML-STP:ELEMENT :LOCAL-NAME "child" :NAMESPACE-URI "http://bar")
Well, since the OP already uses a wrapper function to add elements this isn't neccessary. And I think the underlying confusion came from the (wrong) assumption that an empty namespace (i.e. ns-uri = "") would mean "same ns as parent". That's a rather common misconception stemming from the difference between the xml data model and it's serialisaton. Namespace prefixes belong to the later. BTW: why are you using split-qname in your wrapper? Would you expect to feed "foo:bar" to make-element-in-context?
Thank you both for your suggestions, they will be useful to me when I rewrite my code.
Would it be an idea to add functionality similar to what plexippus-xpath provides via with-namespaces? I.e, a special variable that holds the current set of namespace tag/uri mappings, and have some some additional constructors that use split-qname to extract the tag and look-up the url from the current set of mappings.
Then again, the reason I wrote add-element was to provide an abstraction for the operation of creating a new element with (optional) attributes and (optional) text content and adding it to a parent node. Implementing a mapping mechanism between qnames and uris will not help with this.
Quoting Raymond Wiker (rwiker@gmail.com):
Would it be an idea to add functionality similar to what plexippus-xpath provides via with-namespaces? I.e, a special variable that holds the current set of namespace tag/uri mappings, and have some some additional constructors that use split-qname to extract the tag and look-up the url from the current set of mappings.
Possibly... cxml currently has such a macro only for its serialization API, i.e.
CL-USER> (cxml:with-xml-output (stp:make-builder) (cxml:with-namespace ("a" "http://a") (cxml:with-element "a:b" (cxml:text "xyz")))) #.(CXML-STP-IMPL::DOCUMENT :CHILDREN '(#.(CXML-STP:ELEMENT #| :PARENT of type DOCUMENT |# :CHILDREN '(#.(CXML-STP:TEXT #| :PARENT of type ELEMENT |# :DATA "xyz")) :LOCAL-NAME "b" :NAMESPACE-PREFIX "a" :NAMESPACE-URI "http://a")))
That API can't really modify STP in place though; the builder only knows how to set up a full document.
d.
Greetings all,
Having been away from the XML world for a while, I'm back on a fairly large project using it. While travelling down one of the paths in the rabbit warren, I came across a need to generate a from (probably an XForm) from an XSD. The use case is the specification of data models via the XSD, and quickly generating a form that a human user could use to input data.
It seems that there's *almost* some pipeline of chtml/cxml/cxml-stp that would get us most of the way there, but I haven't found a magic incantation that will do the trick.
Does anyone know of any clever way to go from an XSD to a X/HTML form? It doesn't have to look pretty, just be functional. I do know there will be some things that can't be easily done; that's fine, I expect manual work to reach the final product. I'm just looking for a tool that will get us most of the way there, since we have a large number of input formats. Doesn't have to even be a LISP solution, though that would be much preferred.
Cheers, - Steve