[relaxng-user] Java datatype library: value object->string conversion

Julian Scheid julian at sektor37.de
Thu Nov 4 16:34:52 ICT 2004


Kohsuke Kawaguchi wrote:
> Oh, OK. But if you are doing this, can't you just remember what literal 
> you passed in to Datatype.createValue, along with the context that you 
> passed in?  You can also use .getClass() to find out what the type of 
> the value is for that particular literal.

Many thanks for your suggestions, but unfortunately this doesn't solve 
my problem. Please allow me to outline my situation briefly.

I have a piece of software which reads a grammar and generates a parser 
class and a set of value classes reflecting this grammar.

Suppose I feed a grammar to the system and this grammar contains the 
following fragment:

  <element name="address">
    ...
    <element name="zipcode">
      <data type="zipcode" datatypeLibrary="http://foo/mydatalib"/>
    </element>
  </element>

Given this grammar, my system ought to generate a value class like the 
one below (scoping, getters and setters omitted, boxing issues ignored):

   class Address
   {
      ...
      Integer zipcode;
   }

Let's call this "generation time"; at this time my system only deals 
with a grammar document - as opposed to runtime, when the generated code 
deals with a data document.

In above example I assume that the "zipcode" Datatype's createValue() 
method returns objects of type Integer. But how can my system possibly 
know the type *at generation time*?

In order to use getClass() it would have to call createValue() first, 
but what literal should it pass in? The createValue() implementation 
will likely only return an Integer if a valid zip code literal is being 
passed in, and fail otherwise. But my system doesn't have a sample zip 
code at this point in time, since it doesn't operate on a data document 
at generation time. All information it has at this point comes from the 
grammar, and that doesn't include a sample literal.

This is why a getValueType() method would be very helpful in terms of 
code generation, at least for my approach to data binding.

> 
>> I agree that when it comes to transforming to literals the issue is 
>> somewhat more complex than I indicated. But isn't what's needed 
>> basically a registerNamespace(String uri, String prefix) method in the 
>> context?
> 
> 
> No. My point was that generating code like the following is a lot more 
> work:
> 
>     public static final QName ABC = new QName("foo","bar");
> 
> It's clearly not just an issue of declaring a new namespace.

Let me try to approach the problem from a different angle and briefly 
recollect my understanding of QNames. Please correct me if I'm mistaken.

A QName is a local name together with a namespace, where the namespace 
is identified by a URI.

So a QName could be { foo, http://bar/baz }.

In the following code, both "qname" attributes resolve to this 
particular QName, correct?

<fubar qname="a:foo" xmlns:a="http://bar/baz"/>
<fubar qname="b:foo" xmlns:b="http://bar/baz"/>

When a QName is being read, the Datatype implementation can use the 
ValidationContext to resolve the prefix, yielding the URI. It would then 
store both the local name and the URI in some value object which 
represents the QName semantically. (So the prefix is only a syntactic 
construct and doesn't contribute to a QName semantically.)

Later, when the QName is about to be converted "back" to a literal, the 
following is necessary in order to preserve the QName semantically:
- a prefix needs to be chosen that doesn't conflict with another prefix.
- the prefix needs to be bound to the URI "near" or "above" the literal 
in the output document.

In addition, in terms of readability or "prettiness" of the output document
- the same prefix should be used for the same URI all over the document
- the prefix shouldn't be chosen arbitrarily but rather according to 
user preference, or in a way that a prefix that was used in an input 
document is preserved.

Couldn't all of this be achieved rather easily by a method in the 
context object which, given a namespace URI, returns a prefix for this 
URI and remembers the binding so that the code which writes the XML 
document can output the binding appropriately?

This new context method could use an approach for determining the prefix 
roughly like this:
- lookup the prefix in some registry which has been initialized either 
by the user and/or by the system (if the data model hasn't been 
constructed from scratch but rather has been read from an XML document 
earlier)
- reuse a binding, if a prefix has already been chosen for the namespace 
earlier in the output process
- use a generic prefix if all else fails (like a:, b:, c: ...), possibly 
emitting a warning message.

I may be completely off track, but to me it looks like all that's needed 
to solve the QName issue is this additional context method complementing 
resolveNamespacePrefix(). It seems to me that the facility required for 
output is essentially the inverse of the namespace resolution facility 
used for input.

Am I missing something here?

Thanks for your consideration,

Julian


More information about the relaxng-user mailing list