[jdom-interest] Accessing Child Elements
Peter V. Gadjokov
pvg at c-c-s.com
Wed Sep 6 15:01:46 PDT 2000
Following up on my own post... There is another way of looking at this
which perhaps comes closer to Elioette's i-like-my-namespaces-explicit
worldview. My last proposal assumes that the rules of namespace scoping
should be modeled directly by the API and its implementation. It's
perfectly possible to toss this assumption and get consistent and
intuitive API behaviour. It goes something like this -
All elements have an explicit namespace declaration. How that namespace
declaration is represented in the XML output is the business of the XML
outputter, in the JDOM (java object) representation, all elements
have explicit, immutable namespace declarations with no inheritence
or propagation rules. There are no distinguished namespaces such
as the default namespace - the distinguished nature of the default
namespace is an artifact of the textual representation of XML belongs
in the java<->xml text conversion facilities and not in the core
Java API. The intrinsic methods of element creation and lookup all
require an explicit namespace. All other variants of these methods are
convenience methods with clearly documented semantics appropriate for
the particular method.
What this all means -
new Element("name") - create element in the empty namespace [no change]
This is the only place a specific namespace is assumed and
it is the empty namespace (xmlns="", if declared explicitly in XML
text), for lack of any other sensible choice. If one
wanted to be an anal purist, this constructor could simply be
removed. Users who need it could write a trivial subclass
or trivial factory that provides this functionality.
the namespace-less variants of get/remove child/children all use
the parent/receiver namespace as context. This is intuitive -
that's the only namespace they could possibly assume given that
all elements have a namespace and no namespace is special. If you're
asking an element for another element and provide no namespace, the
only sensible assumption the receiver can make is that you're asking
for something in _its_ namespace. This applies to the getCopy methods
and attribute related methods as well. The lack of 'default namespace'
semantics improves the conceptual simplicity of the API - in the case
of attirbutes, there is no need to explain that default namespaces
do not apply to attributes.
Aside for the changes in Element for implicit lookup, outputters
would have to be modified to treat NO_NAMESPACE as the _empty_ as
opposed to the default namespace. The notion of a default namespace
would not exist in the JDOM. This approach has a certain appeal -
the complexity of the scoping rules is reduced and that makes sense
in an object model - you're navigating an instance graph and you can
easily ask any instance to tell you what it is. In other words,
every Element already has a getNamespace() method, every Element
is already 'explicitly annotated' by virtue of the API. The 'default
namespace' semantics are only useful when the XML is represented
as text, they can arguably help make the textual representation
more compact or more readable. An object model or a Java instance
graph has no such requirement. [A non-xml example of this is is the
representation of Java type names in source and at runtime, in a
particular piece of source a given type might be represented
as Foo, FooMaster.Foo or com.fooborama.FooMaster.Foo, the
runtime only stores/cares about/tracks a stable, unique, FQ'ed name
that can be obtained for any instance of Foo by calling
getClass().getName()]
To use Jason Hunter's example again -
// Create an element in the empty NS (or impossible if the constructor
// were removed entirely)
Element kid = new Element("kid");
// Add the child...
parent.addContent(kid);
// Retreieve the child
parent.getChild("kid");
This would work iff parent were in the empty namespace as kid. It would
not work if parent were in some other namespace. Is that a big deal? I
don't think it is. It may be a little confusing at first to people
who are used to staring at a lot of XML text - but the API should cater
to Java programmers and present a consistent OO model - a model that
allows accurate, deterministic, bidirectional conversion to XML but
is not burdened with every wart and detail of the textual
representation. Chances are, as XML gains popularity, writing and
reading XML text manually will become a less-common chore and almost
all XML manipulation will be done programatically. It seems best to
focus on programmatic representations that are sensible and easy
for programmers to use at the cost of (when neccessary and possible)
of modelling every of the textual representation.
What would the above changes mean for current code?
If you're not using namespaces, everything works as it did before.
If you are using namespaces, expecting some default behaviour other
than some assumption based on the namespace of the receiver is not
sensible. If you are using namespaces, you're best off being explicit
when instantiating (improves the maintainability of
the code anyway) and relying on the implicit lookup only when your
code has a strong built-in knowledge of the structure of the tags
its manipulating (usually the case). Potentially, a convenience
creation method could be added to Element for lazy typists
Element createChild(String name)
{
Element newChild = new Element(name, namespace);
return addContent(newChild);
}
As more and more systems employ XML, particularly for the purposes
of interoperability, namespaces become crucial. We're less
likely to be seeing much code with no namespace use at all as time
goes on - namespace-capable JDOM code should be the assumed to be
the default use-case. The simplicity and ease of writing and using
namespace-capable code should take precedence i.e. if the API is
going to have convenience methods that make assumptions, those
assumptions should be such that make namespace-capable code easier
to write and use.
-pvg
More information about the jdom-interest
mailing list