SanityManager.ASSERT(serializer != null,
"Tried to serialize with uninitialized XML serializer.");
}
serializer.setWriter(sWriter);
DOMSerializer dSer = serializer.asDOMSerializer();
int sz = items.size();
Object obj = null;
/* Step 1: Empty sequence. If we have an empty sequence then we
* won't ever enter the for loop and the call to sWriter.toString()
* at the end of this method will return an empty string, as
* required. Otherwise, for a non-empty sequence our "items"
* list already corresponds to "S1".
*/
// Iterate through the list and serialize each item.
boolean lastItemWasString = false;
for (int i = 0; i < sz; i++)
{
obj = items.get(i);
// if it's a string, then this corresponds to some atomic
// value, so just echo the string as it is.
if (obj instanceof String)
{
/* Step 2: Atomic values. If "obj" is a string then it
* corresponds to some atomic value whose "lexical
* representation" is obj. So we just take that.
*/
if (lastItemWasString)
{
/* Step 3: Adjacent strings. If we have multiple adjacent
* strings then concatenate them with a single space
* between them.
*/
sWriter.write(" ");
}
/* Step 4: Create a Text node from the adjacent strings.
* Since we're just going to serialize the Text node back
* into a string, we short-cut this step by skipping the
* creation of the Text node and just writing the string
* out directly to our serialized stream.
*/
sWriter.write((String)obj);
lastItemWasString = true;
}
else if (obj instanceof Attr)
{
/* Step 7a: Attribute nodes. If there is an Attribute node
* node in the sequence then we have to throw a serialization
* error. NOTE: The rules say we also have to throw an error
* for Namespace nodes, but JAXP doesn't define a "Namespace"
* object per se; it just defines namespace prefixes and URIs
* on other Nodes. So we just check for attributes. If we
* find one then we take note of the fact that the result has
* a parentless attribute node and later, if the user calls
* XMLSERIALIZE on the received XMLDataValue we'll throw the
* error as required. Note that we currently only get here
* for the XMLQUERY operator, which means we're serializing
* a result sequence returned from Xalan and we're going to
* store the serialized version into a Derby XML value. In
* that case the serialization is an internal operation--and
* since the user didn't ask for it, we don't want to throw
* the serialization error here. If we did, then whenever an
* XMLQUERY operation returned a result sequence with a top-
* level attribute in it, the user would see a serialization
* error. That's not correct since it is technically okay for
* the XMLQUERY operation to return a sequence with an attribute
* node; it's just not okay for a user to explicitly try to
* serialize that sequence. So instead of throwing the error
* here, we just take note of the fact that the sequence has
* a top-level attribute. Then later, IF the user makes an
* explicit call to serialize the sequence, we'll throw the
* appropriate error (see XML.XMLSerialize()).
*/
if (xmlVal != null)
xmlVal.markAsHavingTopLevelAttr();
dSer.serialize((Node)obj);
lastItemWasString = false;
}
else
{ // We have a Node, so try to serialize it.
Node n = (Node)obj;
if (n instanceof Text)
{
/* Step 6: Combine adjacent text nodes into a single
* text node. Since we're just going to serialize the
* Text node back into a string, we short-cut this step
* by skipping the creation of a new Text node and just
* writing the text value out directly to our serialized
* stream. Step 6 also says that empty text nodes should
* be dropped--but if the text node is empty, the call
* to getNodeValue() will return an empty string and
* thus we've effectively "dropped" the text node from
* the serialized result. Note: it'd be cleaner to just
* call "serialize()" on the Text node like we do for
* all other Nodes, but Xalan doesn't allow that. So
* use the getNodeValue() method instead.
*/
sWriter.write(n.getNodeValue());
}
else
{
/* Steps 5 and 7b: Copy all non-attribute, non-text
* nodes to the "normalized sequence" and then serialize
* that normalized sequence. We short-cut this by
* just letting Xalan do the serialization for every
* Node in the current list of items that wasn't
* "serialized" as an atomic value, attribute, or
* text node.
*/
dSer.serialize(n);
}
lastItemWasString = false;
}
}