Skip to Content.
Sympa Menu

xom-interest - [XOM-interest] xml:id inconsistency

xom-interest AT lists.ibiblio.org

Subject: XOM API for Processing XML with Java

List archive

Chronological Thread  
  • From: Wolfgang Hoschek <wolfgang.hoschek AT mac.com>
  • To: xom-interest AT lists.ibiblio.org
  • Subject: [XOM-interest] xml:id inconsistency
  • Date: Mon, 14 Aug 2006 12:31:21 -0700

Here's another issue for xom-1.2 CVS and prior, related to http:// marc.theaimsgroup.com/?l=xom-interest&w=2&r=1&s=xml%3Aid&q=b
Two ways of doing the same thing, namely

new Builder()

and

new Builder(new NodeFactory() {}) // empty NodeFactory

These flavours should behave in exactly the same manner (apart from performance artefacts), thereby allowing for alternative ways of building the very same XOM document. Yet, for the following XML file below, the flavours behave differently wrt. whitespace normalization in xml:id attributes:

[hoschek /Users/hoschek/unix/devel/nux] cat /Users/hoschek/unix/devel/ nux/../nux-testdata/XOM/data/xmlid/tests/001_normalize.xml
<doc>
<para xml:id=" te st ">MATCH</para>
</doc>


The reason is that new Builder() uses Attribute.build(), which in turn normalizes whitespace, whereas new Builder(new NodeFactory()) uses the Attribute constructor, which in turn doesn't normalize whitespace, because a line such as

value = normalize(value);

is missing in the constructor Attribute(String name, String URI, String value, Type type) if an xml:id is detected. This inconsistency means that alternative implementations of Builder produce different output.

The same issue arises for setValue(String); it should be consistent with Attribute.build(), but isn't.

An example use case demonstrating the setValue() issue is a small fast utility (NodeBuilder.createAttribute()) for efficient construction of elements and attributes, implemented via a LRU cache of the most recent elements and attributes. For it to be work correctly inside a NodeFactory.createAttribute() implementation, setValue() must be consistent with Attribute.build() wrt. whitespace normalization.


/**
* Contructs and returns a new attribute for the given qualified name and
* namespace URI.
*
* @param qname
* the qualified name of the attribute (must not be null)
* @param uri
* the namespace URI of the attribute
* @param value
* the attribute value (must not be null)
* @param type
* the attribute type (must not be null)
* @return a new attribute
*/
public Attribute createAttribute(String qname, String uri, String value, Attribute.Type type) {
if (uri == null) uri = "";
if ("xml:id".equals(qname)) {
type = Attribute.Type.ID; // avoids exception in
Attribute.setType()
}

Attribute attr = (Attribute) attributes.get(qname, uri); // look into cache
if (attr == null) {
attr = new Attribute(qname, uri, value, type);
attributes.put(qname, uri, attr);
return new Attribute(attr); // copy constructor is
fast
}
attr = new Attribute(attr); // copy constructor is fast
if (attr.getType() != type) attr.setType(type);
attr.setValue(value);
return attr;
}

I'd recommend for XOM to be consistent: either always normalize, or never normalize, in all of Attribute.build(), new Attribute(...) and Attribute.setValue(...)

Example fix (others are possible as well):

public void setValue(String value) {
if (isXMLID()) value = normalize(value); // WH
_setValue(value);
}

public Attribute(
String name, String URI, String value, Type type) {

...
_setNamespace(prefix, URI);
if (isXMLID()) value = normalize(value); // WH
_setValue(value);
if (isXMLID()) {
_setType(Attribute.Type.ID);
}
else {
_setType(type);
}
}

Wolfgang.




  • [XOM-interest] xml:id inconsistency, Wolfgang Hoschek, 08/14/2006

Archive powered by MHonArc 2.6.24.

Top of Page