Niklas Gustavsson wrote: > On Sun, May 9, 2010 at 9:52 PM, Bernd Fondermann <[email protected]> > wrote: >> This example is especially appropriate, as it includes beer: > > We like that of course :-) > >> <?xml version='1.0'?> >> <Beers> >> <!-- the default namespace inside tables is that of HTML --> >> <table xmlns='http://www.w3.org/1999/xhtml'> >> <th><td>Name</td><td>Origin</td><td>Description</td></th> >> <tr> >> <!-- no default namespace inside table cells --> >> <td><brandName xmlns="">Huntsman</brandName></td> >> <td><origin xmlns="">Bath, UK</origin></td> >> <td> >> <details xmlns=""><class>Bitter</class><hop>Fuggles</hop> >> <pro>Wonderful hop, light alcohol, good summer beer</pro> >> <con>Fragile; excessive variance pub to pub</con> >> </details> >> </td> >> </tr> >> </table> >> </Beers> >> >> Now, I'd like to have an API like this: >> builder.add("table", "http://www.w3.org/1999/xhtml"). >> add("th"). >> add("tf"). >> addText("Name") ... >> >> and *not* >> builder.add("table", "http://www.w3.org/1999/xhtml"). >> add("th", "http://www.w3.org/1999/xhtml"). >> add("tf", "http://www.w3.org/1999/xhtml"). >> addText("Name") ... >> >> while you'd like it the other way round, right? > > Yes (of course, you would likely use a constant rather than a string, > but that's besides the point here). > >> Reason for my position: This is straihtforward. You don't redefine java >> variables when a new scope opens. You'd just redefine them to >> shadow/override the outer scoped variable. >> The inner XML elements are not arbitrary. Within a table, you'd expect >> td, tr etc. to occur. No need to redefine the namespace. >> However, if non-table elements occur, the namespace gets reset explicitly. > > I'm not sure I follow along perfectly well here. But, I'll attempt to > give an example of why I think inheriting the namespace in the XML > creation step would be confusing. Let's take the following function > that creates <item> elements in a MUC implementation: > > private XMLElement createItem(XMLElementBuilder builder) { > builder.startInnerElement("item"); > ... > } > > Now, in MUC, <item> elements can be contained both in the > http://jabber.org/protocol/muc#user and > http://jabber.org/protocol/muc#admin namespaces. Which one would this > be in? To find out, I would have to backtrack to code to find out > where the parent <x> element is created and see what namespace that is > in.
Well, if <item> has the same semantic in all cases, this would be perfect. If it carries different semantics for both #user and #admin, you'd have different signatures for the method anyway, to propagate these semantics. > I would rather prefer the namespace be explicit. > >> And I don't think you can get rid of looking up outer namespaces in any >> serious implementation. In the second example, where every add() has an >> explicit namespace declaration, one would >> * either repeatedly render the declared xmlns on every element, no >> tracking of outer ns needed >> * or, not repeat rendering the declared xmlns, (like *all* XML examples >> I've seen so far) which can only be achieved by keeping track of what >> the current namespace is. >> >> I don't think XML like this: >> <table xmlns='http://www.w3.org/1999/xhtml'> >> <th xmlns='http://www.w3.org/1999/xhtml'> >> <td xmlns='http://www.w3.org/1999/xhtml'>Name >> ... >> would be very compatible with XMPP clients. And would put much more >> bytes on the wire than neccessary. > > Oh, no one is saying this is the XML we should render, and nor do we > currently. Instead, the renderer keeps a stack of the default > namespaces and only outputs the xmlns attribute when needed. This is > the same as the "renderers" (most APIs use the term "writer") does in > the other previously mentioned APIs. So basically, you're proposing to design an API which requires saying: * I want to use ns 'http:123' on element 'iq' * I still want to use ns 'http:123' on inner element 'query' * I still want to use ns 'http:123' on inner element 'items' * Yes, I still want to use ns 'http:123' on inner element 'item', really! which is redundant. And you justify this by emphasizing that everybody else does which is ok from an XML parser PoV, but not so much from a Vysper PoV. Why? Because the impact of implementing this would be: * Changing a lot of working code, potentially introducing bugs, without adding any information which isn't already there. * Making stanza creation much more verbose, cluttering namespaces all over the place. * Tracking everywhere if a stream is c2s or s2s, to appropriately be able to add xmlns='jabber:client' vs. xmlns='jabber:server' I don't want to go through all this. If the renderer/writer is intelligent enough to derive the ns, then please let's follow "DRY", regardless of other APIs. XMPP doesn't need a full blown XML parser. So I can see basically two options: 1. Introduce (aka. keep) ways to make the renderer intelligent enough (well, effectively make the API intelligent enough). 2. Rollback Vysper to it's own, buggy-but-sufficient XML handling code. Bernd
