SAX2DTMpublic class SAX2DTM extends DTMDefaultBaseIterators implements ErrorHandler, DeclHandler, LexicalHandler, EntityResolver, DTDHandler, ContentHandlerThis class implements a DTM that tends to be optimized more for speed than
for compactness, that is constructed via SAX2 ContentHandler events. |
Fields Summary |
---|
private static final boolean | DEBUGSet true to monitor SAX events and similar diagnostic info. | private IncrementalSAXSource | m_incrementalSAXSourceIf we're building the model incrementally on demand, we need to
be able to tell the source when to send us more data.
Note that if this has not been set, and you attempt to read ahead
of the current build point, we'll probably throw a null-pointer
exception. We could try to wait-and-retry instead, as a very poor
fallback, but that has all the known problems with multithreading
on multiprocessors and we Don't Want to Go There. | protected FastStringBuffer | m_charsAll the character content, including attribute values, are stored in
this buffer.
%REVIEW% Should this have an option of being shared across DTMs?
Sequentially only; not threadsafe... Currently, I think not.
%REVIEW% Initial size was pushed way down to reduce weight of RTFs.
pending reduction in number of RTF DTMs. Now that we're sharing a DTM
between RTFs, and tail-pruning... consider going back to the larger/faster.
Made protected rather than private so SAX2RTFDTM can access it. | protected SuballocatedIntVector | m_dataThis vector holds offset and length data. | protected transient IntStack | m_parentsThe parent stack, needed only for construction.
Made protected rather than private so SAX2RTFDTM can access it. | protected transient int | m_previousThe current previous node, needed only for construction time.
Made protected rather than private so SAX2RTFDTM can access it. | protected transient Vector | m_prefixMappingsNamespace support, only relevent at construction time.
Made protected rather than private so SAX2RTFDTM can access it. | protected transient IntStack | m_contextIndexesNamespace support, only relevent at construction time.
Made protected rather than private so SAX2RTFDTM can access it. | protected transient int | m_textTypeType of next characters() event within text block in prgress. | protected transient int | m_coalescedTextTypeType of coalesced text block. See logic in the characters()
method. | protected transient Locator | m_locatorThe SAX Document locator | private transient String | m_systemIdThe SAX Document system-id | protected transient boolean | m_insideDTDWe are inside the DTD. This is used for ignoring comments. | protected DTMTreeWalker | m_walkerTree Walker for dispatchToEvents. | protected DTMStringPool | m_valuesOrPrefixespool of string values that come as strings. | protected boolean | m_endDocumentOccuredEnd document has been reached.
Made protected rather than private so SAX2RTFDTM can access it. | protected SuballocatedIntVector | m_dataOrQNameData or qualified name values, one array element for each node. | protected Hashtable | m_idAttributesThis table holds the ID string to node associations, for
XML IDs. | static final String[] | m_fixednamesfixed dom-style names. | private Vector | m_entitiesVector of entities. Each record is composed of four Strings:
publicId, systemID, notationName, and name. | private static final int | ENTITY_FIELD_PUBLICIDm_entities public ID offset. | private static final int | ENTITY_FIELD_SYSTEMIDm_entities system ID offset. | private static final int | ENTITY_FIELD_NOTATIONNAMEm_entities notation name offset. | private static final int | ENTITY_FIELD_NAMEm_entities name offset. | private static final int | ENTITY_FIELDS_PERNumber of entries per record for m_entities. | protected int | m_textPendingStartThe starting offset within m_chars for the text or
CDATA_SECTION node currently being acumulated,
or -1 if there is no text node in progress | protected boolean | m_useSourceLocationPropertyDescribes whether information about document source location
should be maintained or not.
Made protected for access by SAX2RTFDTM. | protected static boolean | m_source_locationDescribes whether information about document source location
should be maintained or not. This static flag is set by TransformerFactoryImpl. | protected StringVector | m_sourceSystemIdMade protected for access by SAX2RTFDTM. | protected IntVector | m_sourceLineMade protected for access by SAX2RTFDTM. | protected IntVector | m_sourceColumnMade protected for access by SAX2RTFDTM. | boolean | m_pastFirstElement |
Constructors Summary |
---|
public SAX2DTM(DTMManager mgr, Source source, int dtmIdentity, DTMWSFilter whiteSpaceFilter, XMLStringFactory xstringfactory, boolean doIndexing)Construct a SAX2DTM object using the default block size.
this(mgr, source, dtmIdentity, whiteSpaceFilter,
xstringfactory, doIndexing, DEFAULT_BLOCKSIZE, true, false);
| public SAX2DTM(DTMManager mgr, Source source, int dtmIdentity, DTMWSFilter whiteSpaceFilter, XMLStringFactory xstringfactory, boolean doIndexing, int blocksize, boolean usePrevsib, boolean newNameTable)Construct a SAX2DTM object ready to be constructed from SAX2
ContentHandler events.
super(mgr, source, dtmIdentity, whiteSpaceFilter,
xstringfactory, doIndexing, blocksize, usePrevsib, newNameTable);
// %OPT% Use smaller sizes for all internal storage units when
// the blocksize is small. This reduces the cost of creating an RTF.
if (blocksize <= 64)
{
m_data = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS_SMALL);
m_dataOrQName = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS_SMALL);
m_valuesOrPrefixes = new DTMStringPool(16);
m_chars = new FastStringBuffer(7, 10);
m_contextIndexes = new IntStack(4);
m_parents = new IntStack(4);
}
else
{
m_data = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS);
m_dataOrQName = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS);
m_valuesOrPrefixes = new DTMStringPool();
m_chars = new FastStringBuffer(10, 13);
m_contextIndexes = new IntStack();
m_parents = new IntStack();
}
// %REVIEW% Initial size pushed way down to reduce weight of RTFs
// (I'm not entirely sure 0 would work, so I'm playing it safe for now.)
//m_data = new SuballocatedIntVector(doIndexing ? (1024*2) : 512, 1024);
//m_data = new SuballocatedIntVector(blocksize);
m_data.addElement(0); // Need placeholder in case index into here must be <0.
//m_dataOrQName = new SuballocatedIntVector(blocksize);
// m_useSourceLocationProperty=com.sun.org.apache.xalan.internal.processor.TransformerFactoryImpl.m_source_location;
m_useSourceLocationProperty = m_source_location;
m_sourceSystemId = (m_useSourceLocationProperty) ? new StringVector() : null;
m_sourceLine = (m_useSourceLocationProperty) ? new IntVector() : null;
m_sourceColumn = (m_useSourceLocationProperty) ? new IntVector() : null;
|
Methods Summary |
---|
protected int | _dataOrQName(int identity)Get the data or qualified name for the given node identity.
if (identity < m_size)
return m_dataOrQName.elementAt(identity);
// Check to see if the information requested has been processed, and,
// if not, advance the iterator until we the information has been
// processed.
while (true)
{
boolean isMore = nextNode();
if (!isMore)
return NULL;
else if (identity < m_size)
return m_dataOrQName.elementAt(identity);
}
| protected void | addNewDTMID(int nodeIndex)Get a new DTM ID beginning at the specified node index.
try
{
if(m_mgr==null)
throw new ClassCastException();
// Handle as Extended Addressing
DTMManagerDefault mgrD=(DTMManagerDefault)m_mgr;
int id=mgrD.getFirstFreeDTMID();
mgrD.addDTM(this,id,nodeIndex);
m_dtmIdent.addElement(id<<DTMManager.IDENT_DTM_NODE_BITS);
}
catch(ClassCastException e)
{
// %REVIEW% Wrong error message, but I've been told we're trying
// not to add messages right not for I18N reasons.
// %REVIEW% Should this be a Fatal Error?
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_NO_DTMIDS_AVAIL, null));//"No more DTM IDs are available";
}
| protected int | addNode(int type, int expandedTypeID, int parentIndex, int previousSibling, int dataOrPrefix, boolean canHaveFirstChild)Construct the node map from the node.
// Common to all nodes:
int nodeIndex = m_size++;
// Have we overflowed a DTM Identity's addressing range?
if(m_dtmIdent.size() == (nodeIndex>>>DTMManager.IDENT_DTM_NODE_BITS))
{
addNewDTMID(nodeIndex);
}
m_firstch.addElement(canHaveFirstChild ? NOTPROCESSED : DTM.NULL);
m_nextsib.addElement(NOTPROCESSED);
m_parent.addElement(parentIndex);
m_exptype.addElement(expandedTypeID);
m_dataOrQName.addElement(dataOrPrefix);
if (m_prevsib != null) {
m_prevsib.addElement(previousSibling);
}
if (DTM.NULL != previousSibling) {
m_nextsib.setElementAt(nodeIndex,previousSibling);
}
if (m_locator != null && m_useSourceLocationProperty) {
setSourceLocation();
}
// Note that nextSibling is not processed until charactersFlush()
// is called, to handle successive characters() events.
// Special handling by type: Declare namespaces, attach first child
switch(type)
{
case DTM.NAMESPACE_NODE:
declareNamespaceInContext(parentIndex,nodeIndex);
break;
case DTM.ATTRIBUTE_NODE:
break;
default:
if (DTM.NULL == previousSibling && DTM.NULL != parentIndex) {
m_firstch.setElementAt(nodeIndex,parentIndex);
}
break;
}
return nodeIndex;
| public void | attributeDecl(java.lang.String eName, java.lang.String aName, java.lang.String type, java.lang.String valueDefault, java.lang.String value)Report an attribute type declaration.
Only the effective (first) declaration for an attribute will
be reported. The type will be one of the strings "CDATA",
"ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
"ENTITIES", or "NOTATION", or a parenthesized token group with
the separator "|" and all whitespace removed.
// no op
| public void | characters(char[] ch, int start, int length)Receive notification of character data inside an element.
By default, do nothing. Application writers may override this
method to take specific actions for each chunk of character data
(such as adding the data to a node or buffer, or printing it to
a file).
if (m_textPendingStart == -1) // First one in this block
{
m_textPendingStart = m_chars.size();
m_coalescedTextType = m_textType;
}
// Type logic: If all adjacent text is CDATASections, the
// concatentated text is treated as a single CDATASection (see
// initialization above). If any were ordinary Text, the whole
// thing is treated as Text. This may be worth %REVIEW%ing.
else if (m_textType == DTM.TEXT_NODE)
{
m_coalescedTextType = DTM.TEXT_NODE;
}
m_chars.append(ch, start, length);
| protected void | charactersFlush()Check whether accumulated text should be stripped; if not,
append the appropriate flavor of text/cdata node.
if (m_textPendingStart >= 0) // -1 indicates no-text-in-progress
{
int length = m_chars.size() - m_textPendingStart;
boolean doStrip = false;
if (getShouldStripWhitespace())
{
doStrip = m_chars.isWhitespace(m_textPendingStart, length);
}
if (doStrip)
m_chars.setLength(m_textPendingStart); // Discard accumulated text
else
{
int exName = m_expandedNameTable.getExpandedTypeID(DTM.TEXT_NODE);
int dataIndex = m_data.size();
m_previous = addNode(m_coalescedTextType, exName,
m_parents.peek(), m_previous, dataIndex, false);
m_data.addElement(m_textPendingStart);
m_data.addElement(length);
}
// Reset for next text block
m_textPendingStart = -1;
m_textType = m_coalescedTextType = DTM.TEXT_NODE;
}
| public void | clearCoRoutine()Ask the CoRoutine parser to doTerminate and clear the reference.
clearCoRoutine(true);
| public void | clearCoRoutine(boolean callDoTerminate)Ask the CoRoutine parser to doTerminate and clear the reference. If
the CoRoutine parser has already been cleared, this will have no effect.
if (null != m_incrementalSAXSource)
{
if (callDoTerminate)
m_incrementalSAXSource.deliverMoreNodes(false);
m_incrementalSAXSource = null;
}
| public void | comment(char[] ch, int start, int length)Report an XML comment anywhere in the document.
This callback will be used for comments inside or outside the
document element, including comments in the external DTD
subset (if read).
if (m_insideDTD) // ignore comments if we're inside the DTD
return;
charactersFlush();
int exName = m_expandedNameTable.getExpandedTypeID(DTM.COMMENT_NODE);
// For now, treat comments as strings... I guess we should do a
// seperate FSB buffer instead.
int dataIndex = m_valuesOrPrefixes.stringToIndex(new String(ch, start,
length));
m_previous = addNode(DTM.COMMENT_NODE, exName,
m_parents.peek(), m_previous, dataIndex, false);
| protected boolean | declAlreadyDeclared(java.lang.String prefix)Check if a declaration has already been made for a given prefix.
int startDecls = m_contextIndexes.peek();
java.util.Vector prefixMappings = m_prefixMappings;
int nDecls = prefixMappings.size();
for (int i = startDecls; i < nDecls; i += 2)
{
String prefixDecl = (String) prefixMappings.elementAt(i);
if (prefixDecl == null)
continue;
if (prefixDecl.equals(prefix))
return true;
}
return false;
| public void | dispatchCharactersEvents(int nodeHandle, org.xml.sax.ContentHandler ch, boolean normalize)Directly call the
characters method on the passed ContentHandler for the
string-value of the given node (see http://www.w3.org/TR/xpath#data-model
for the definition of a node's string-value). Multiple calls to the
ContentHandler's characters methods may well occur for a single call to
this method.
int identity = makeNodeIdentity(nodeHandle);
if (identity == DTM.NULL)
return;
int type = _type(identity);
if (isTextType(type))
{
int dataIndex = m_dataOrQName.elementAt(identity);
int offset = m_data.elementAt(dataIndex);
int length = m_data.elementAt(dataIndex + 1);
if(normalize)
m_chars.sendNormalizedSAXcharacters(ch, offset, length);
else
m_chars.sendSAXcharacters(ch, offset, length);
}
else
{
int firstChild = _firstch(identity);
if (DTM.NULL != firstChild)
{
int offset = -1;
int length = 0;
int startNode = identity;
identity = firstChild;
do {
type = _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
if (-1 == offset)
{
offset = m_data.elementAt(dataIndex);
}
length += m_data.elementAt(dataIndex + 1);
}
identity = getNextNodeIdentity(identity);
} while (DTM.NULL != identity && (_parent(identity) >= startNode));
if (length > 0)
{
if(normalize)
m_chars.sendNormalizedSAXcharacters(ch, offset, length);
else
m_chars.sendSAXcharacters(ch, offset, length);
}
}
else if(type != DTM.ELEMENT_NODE)
{
int dataIndex = _dataOrQName(identity);
if (dataIndex < 0)
{
dataIndex = -dataIndex;
dataIndex = m_data.elementAt(dataIndex + 1);
}
String str = m_valuesOrPrefixes.indexToString(dataIndex);
if(normalize)
FastStringBuffer.sendNormalizedSAXcharacters(str.toCharArray(),
0, str.length(), ch);
else
ch.characters(str.toCharArray(), 0, str.length());
}
}
| public void | dispatchToEvents(int nodeHandle, org.xml.sax.ContentHandler ch)Directly create SAX parser events from a subtree.
DTMTreeWalker treeWalker = m_walker;
ContentHandler prevCH = treeWalker.getcontentHandler();
if (null != prevCH)
{
treeWalker = new DTMTreeWalker();
}
treeWalker.setcontentHandler(ch);
treeWalker.setDTM(this);
try
{
treeWalker.traverse(nodeHandle);
}
finally
{
treeWalker.setcontentHandler(null);
}
| public void | elementDecl(java.lang.String name, java.lang.String model)Report an element type declaration.
The content model will consist of the string "EMPTY", the
string "ANY", or a parenthesised group, optionally followed
by an occurrence indicator. The model will be normalized so
that all whitespace is removed,and will include the enclosing
parentheses.
// no op
| public void | endCDATA()Report the end of a CDATA section.
m_textType = DTM.TEXT_NODE;
| public void | endDTD()Report the end of DTD declarations.
m_insideDTD = false;
| public void | endDocument()Receive notification of the end of the document.
if (DEBUG)
System.out.println("endDocument");
charactersFlush();
m_nextsib.setElementAt(NULL,0);
if (m_firstch.elementAt(0) == NOTPROCESSED)
m_firstch.setElementAt(NULL,0);
if (DTM.NULL != m_previous)
m_nextsib.setElementAt(DTM.NULL,m_previous);
m_parents = null;
m_prefixMappings = null;
m_contextIndexes = null;
m_endDocumentOccured = true;
// Bugzilla 4858: throw away m_locator. we cache m_systemId
m_locator = null;
| public void | endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName)Receive notification of the end of an element.
By default, do nothing. Application writers may override this
method in a subclass to take specific actions at the end of
each element (such as finalising a tree node or writing
output to a file).
if (DEBUG)
System.out.println("endElement: uri: " + uri + ", localname: "
+ localName + ", qname: "+qName);
charactersFlush();
// If no one noticed, startPrefixMapping is a drag.
// Pop the context for the last child (the one pushed by startElement)
m_contextIndexes.quickPop(1);
// Do it again for this one (the one pushed by the last endElement).
int topContextIndex = m_contextIndexes.peek();
if (topContextIndex != m_prefixMappings.size()) {
m_prefixMappings.setSize(topContextIndex);
}
int lastNode = m_previous;
m_previous = m_parents.pop();
// If lastNode is still DTM.NULL, this element had no children
if (DTM.NULL == lastNode)
m_firstch.setElementAt(DTM.NULL,m_previous);
else
m_nextsib.setElementAt(DTM.NULL,lastNode);
popShouldStripWhitespace();
| public void | endEntity(java.lang.String name)Report the end of an entity.
// no op
| public void | endPrefixMapping(java.lang.String prefix)Receive notification of the end of a Namespace mapping.
By default, do nothing. Application writers may override this
method in a subclass to take specific actions at the end of
each prefix mapping.
if (DEBUG)
System.out.println("endPrefixMapping: prefix: " + prefix);
if(null == prefix)
prefix = "";
int index = m_contextIndexes.peek() - 1;
do
{
index = m_prefixMappings.indexOf(prefix, ++index);
} while ( (index >= 0) && ((index & 0x01) == 0x01) );
if (index > -1)
{
m_prefixMappings.setElementAt("%@$#^@#", index);
m_prefixMappings.setElementAt("%@$#^@#", index + 1);
}
// no op
| public void | error(org.xml.sax.SAXParseException e)Receive notification of a recoverable parser error.
The default implementation does nothing. Application writers
may override this method in a subclass to take specific actions
for each error, such as inserting the message in a log file or
printing it to the console.
throw e;
| public void | externalEntityDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId)Report a parsed external entity declaration.
Only the effective (first) declaration for each entity
will be reported.
// no op
| public void | fatalError(org.xml.sax.SAXParseException e)Report a fatal XML parsing error.
The default implementation throws a SAXParseException.
Application writers may override this method in a subclass if
they need to take specific actions for each fatal error (such as
collecting all of the errors into a single report): in any case,
the application must stop all regular processing when this
method is invoked, since the document is no longer reliable, and
the parser may no longer report parsing events.
throw e;
| public int | getAttributeNode(int nodeHandle, java.lang.String namespaceURI, java.lang.String name)Retrieves an attribute node by by qualified name and namespace URI.
for (int attrH = getFirstAttribute(nodeHandle); DTM.NULL != attrH;
attrH = getNextAttribute(attrH))
{
String attrNS = getNamespaceURI(attrH);
String attrName = getLocalName(attrH);
boolean nsMatch = namespaceURI == attrNS
|| (namespaceURI != null
&& namespaceURI.equals(attrNS));
if (nsMatch && name.equals(attrName))
return attrH;
}
return DTM.NULL;
| public org.xml.sax.ContentHandler | getContentHandler()getContentHandler returns "our SAX builder" -- the thing that
someone else should send SAX events to in order to extend this
DTM model.
%REVIEW% Should this return null if constrution already done/begun?
if (m_incrementalSAXSource instanceof IncrementalSAXSource_Filter)
return (ContentHandler) m_incrementalSAXSource;
else
return this;
| public org.xml.sax.DTDHandler | getDTDHandler()Return this DTM's DTDHandler.
return this;
| public org.xml.sax.ext.DeclHandler | getDeclHandler()Return this DTM's DeclHandler.
return this;
| public java.lang.String | getDocumentTypeDeclarationPublicIdentifier()Return the public identifier of the external subset,
normalized as described in 4.2.2 External Entities [XML]. If there is
no external subset or if it has no public identifier, this property
has no value.
/** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");
return null;
| public java.lang.String | getDocumentTypeDeclarationSystemIdentifier()A document type declaration information item has the following properties:
1. [system identifier] The system identifier of the external subset, if
it exists. Otherwise this property has no value.
/** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");
return null;
| public int | getElementById(java.lang.String elementId)Returns the Element whose ID is given by
elementId . If no such element exists, returns
DTM.NULL . Behavior is not defined if more than one element
has this ID . Attributes (including those
with the name "ID") are not of type ID unless so defined by DTD/Schema
information available to the DTM implementation.
Implementations that do not know whether attributes are of type ID or
not are expected to return DTM.NULL .
%REVIEW% Presumably IDs are still scoped to a single document,
and this operation searches only within a single document, right?
Wouldn't want collisions between DTMs in the same process.
Integer intObj;
boolean isMore = true;
do
{
intObj = (Integer) m_idAttributes.get(elementId);
if (null != intObj)
return makeNodeHandle(intObj.intValue());
if (!isMore || m_endDocumentOccured)
break;
isMore = nextNode();
}
while (null == intObj);
return DTM.NULL;
| public org.xml.sax.EntityResolver | getEntityResolver()Return this DTM's EntityResolver.
return this;
| public org.xml.sax.ErrorHandler | getErrorHandler()Return this DTM's ErrorHandler.
return this;
| public int | getIdForNamespace(java.lang.String uri)Get a prefix either from the uri mapping, or just make
one up!
return m_valuesOrPrefixes.stringToIndex(uri);
| public org.xml.sax.ext.LexicalHandler | getLexicalHandler()Return this DTM's lexical handler.
%REVIEW% Should this return null if constrution already done/begun?
if (m_incrementalSAXSource instanceof IncrementalSAXSource_Filter)
return (LexicalHandler) m_incrementalSAXSource;
else
return this;
| public java.lang.String | getLocalName(int nodeHandle)Given a node handle, return its XPath-style localname.
(As defined in Namespaces, this is the portion of the name after any
colon character).
return m_expandedNameTable.getLocalName(_exptype(makeNodeIdentity(nodeHandle)));
| public java.lang.String | getNamespaceURI(int nodeHandle)Given a node handle, return its DOM-style namespace URI
(As defined in Namespaces, this is the declared URI which this node's
prefix -- or default in lieu thereof -- was mapped to.)
%REVIEW% Null or ""? -sb
return m_expandedNameTable.getNamespace(_exptype(makeNodeIdentity(nodeHandle)));
| public java.lang.String | getNamespaceURI(java.lang.String prefix)Get a prefix either from the qname or from the uri mapping, or just make
one up!
String uri = "";
int prefixIndex = m_contextIndexes.peek() - 1 ;
if(null == prefix)
prefix = "";
do
{
prefixIndex = m_prefixMappings.indexOf(prefix, ++prefixIndex);
} while ( (prefixIndex >= 0) && (prefixIndex & 0x01) == 0x01);
if (prefixIndex > -1)
{
uri = (String) m_prefixMappings.elementAt(prefixIndex + 1);
}
return uri;
| protected int | getNextNodeIdentity(int identity)Get the next node identity value in the list, and call the iterator
if it hasn't been added yet.
identity += 1;
while (identity >= m_size)
{
if (null == m_incrementalSAXSource)
return DTM.NULL;
nextNode();
}
return identity;
| public java.lang.String | getNodeName(int nodeHandle)Given a node handle, return its DOM-style node name. This will
include names such as #text or #document.
int expandedTypeID = getExpandedTypeID(nodeHandle);
// If just testing nonzero, no need to shift...
int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
if (0 == namespaceID)
{
// Don't retrieve name until/unless needed
// String name = m_expandedNameTable.getLocalName(expandedTypeID);
int type = getNodeType(nodeHandle);
if (type == DTM.NAMESPACE_NODE)
{
if (null == m_expandedNameTable.getLocalName(expandedTypeID))
return "xmlns";
else
return "xmlns:" + m_expandedNameTable.getLocalName(expandedTypeID);
}
else if (0 == m_expandedNameTable.getLocalNameID(expandedTypeID))
{
return m_fixednames[type];
}
else
return m_expandedNameTable.getLocalName(expandedTypeID);
}
else
{
int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));
if (qnameIndex < 0)
{
qnameIndex = -qnameIndex;
qnameIndex = m_data.elementAt(qnameIndex);
}
return m_valuesOrPrefixes.indexToString(qnameIndex);
}
| public java.lang.String | getNodeNameX(int nodeHandle)Given a node handle, return the XPath node name. This should be
the name as described by the XPath data model, NOT the DOM-style
name.
int expandedTypeID = getExpandedTypeID(nodeHandle);
int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
if (0 == namespaceID)
{
String name = m_expandedNameTable.getLocalName(expandedTypeID);
if (name == null)
return "";
else
return name;
}
else
{
int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));
if (qnameIndex < 0)
{
qnameIndex = -qnameIndex;
qnameIndex = m_data.elementAt(qnameIndex);
}
return m_valuesOrPrefixes.indexToString(qnameIndex);
}
| public java.lang.String | getNodeValue(int nodeHandle)Given a node handle, return its node value. This is mostly
as defined by the DOM, but may ignore some conveniences.
int identity = makeNodeIdentity(nodeHandle);
int type = _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
int offset = m_data.elementAt(dataIndex);
int length = m_data.elementAt(dataIndex + 1);
// %OPT% We should cache this, I guess.
return m_chars.getString(offset, length);
}
else if (DTM.ELEMENT_NODE == type || DTM.DOCUMENT_FRAGMENT_NODE == type
|| DTM.DOCUMENT_NODE == type)
{
return null;
}
else
{
int dataIndex = _dataOrQName(identity);
if (dataIndex < 0)
{
dataIndex = -dataIndex;
dataIndex = m_data.elementAt(dataIndex + 1);
}
return m_valuesOrPrefixes.indexToString(dataIndex);
}
| public int | getNumberOfNodes()Get the number of nodes that have been added.
return m_size;
| public java.lang.String | getPrefix(int nodeHandle)Given a namespace handle, return the prefix that the namespace decl is
mapping.
Given a node handle, return the prefix used to map to the namespace.
%REVIEW% Are you sure you want "" for no prefix?
%REVIEW-COMMENT% I think so... not totally sure. -sb
int identity = makeNodeIdentity(nodeHandle);
int type = _type(identity);
if (DTM.ELEMENT_NODE == type)
{
int prefixIndex = _dataOrQName(identity);
if (0 == prefixIndex)
return "";
else
{
String qname = m_valuesOrPrefixes.indexToString(prefixIndex);
return getPrefix(qname, null);
}
}
else if (DTM.ATTRIBUTE_NODE == type)
{
int prefixIndex = _dataOrQName(identity);
if (prefixIndex < 0)
{
prefixIndex = m_data.elementAt(-prefixIndex);
String qname = m_valuesOrPrefixes.indexToString(prefixIndex);
return getPrefix(qname, null);
}
}
return "";
| public java.lang.String | getPrefix(java.lang.String qname, java.lang.String uri)Get a prefix either from the qname or from the uri mapping, or just make
one up!
String prefix;
int uriIndex = -1;
if (null != uri && uri.length() > 0)
{
do
{
uriIndex = m_prefixMappings.indexOf(uri, ++uriIndex);
} while ( (uriIndex & 0x01) == 0);
if (uriIndex >= 0)
{
prefix = (String) m_prefixMappings.elementAt(uriIndex - 1);
}
else if (null != qname)
{
int indexOfNSSep = qname.indexOf(':");
if (qname.equals("xmlns"))
prefix = "";
else if (qname.startsWith("xmlns:"))
prefix = qname.substring(indexOfNSSep + 1);
else
prefix = (indexOfNSSep > 0)
? qname.substring(0, indexOfNSSep) : null;
}
else
{
prefix = null;
}
}
else if (null != qname)
{
int indexOfNSSep = qname.indexOf(':");
if (indexOfNSSep > 0)
{
if (qname.startsWith("xmlns:"))
prefix = qname.substring(indexOfNSSep + 1);
else
prefix = qname.substring(0, indexOfNSSep);
}
else
{
if (qname.equals("xmlns"))
prefix = "";
else
prefix = null;
}
}
else
{
prefix = null;
}
return prefix;
| public javax.xml.transform.SourceLocator | getSourceLocatorFor(int node)Retrieve the SourceLocator associated with a specific node.
This is only meaningful if the XalanProperties.SOURCE_LOCATION flag was
set True using setProperty; if it was never set, or was set false, we
will return null.
(We _could_ return a locator with the document's base URI and bogus
line/column information. Trying that; see the else clause.)
if (m_useSourceLocationProperty)
{
node = makeNodeIdentity(node);
return new NodeLocator(null,
m_sourceSystemId.elementAt(node),
m_sourceLine.elementAt(node),
m_sourceColumn.elementAt(node));
}
else if(m_locator!=null)
{
return new NodeLocator(null,m_locator.getSystemId(),-1,-1);
}
else if(m_systemId!=null)
{
return new NodeLocator(null,m_systemId,-1,-1);
}
return null;
| public com.sun.org.apache.xml.internal.utils.XMLString | getStringValue(int nodeHandle)Get the string-value of a node as a String object
(see http://www.w3.org/TR/xpath#data-model
for the definition of a node's string-value).
int identity = makeNodeIdentity(nodeHandle);
int type;
if(identity==DTM.NULL) // Separate lines because I wanted to breakpoint it
type = DTM.NULL;
else
type= _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
int offset = m_data.elementAt(dataIndex);
int length = m_data.elementAt(dataIndex + 1);
return m_xstrf.newstr(m_chars, offset, length);
}
else
{
int firstChild = _firstch(identity);
if (DTM.NULL != firstChild)
{
int offset = -1;
int length = 0;
int startNode = identity;
identity = firstChild;
do {
type = _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
if (-1 == offset)
{
offset = m_data.elementAt(dataIndex);
}
length += m_data.elementAt(dataIndex + 1);
}
identity = getNextNodeIdentity(identity);
} while (DTM.NULL != identity && (_parent(identity) >= startNode));
if (length > 0)
{
return m_xstrf.newstr(m_chars, offset, length);
}
}
else if(type != DTM.ELEMENT_NODE)
{
int dataIndex = _dataOrQName(identity);
if (dataIndex < 0)
{
dataIndex = -dataIndex;
dataIndex = m_data.elementAt(dataIndex + 1);
}
return m_xstrf.newstr(m_valuesOrPrefixes.indexToString(dataIndex));
}
}
return m_xstrf.emptystr();
| public java.lang.String | getUnparsedEntityURI(java.lang.String name)The getUnparsedEntityURI function returns the URI of the unparsed
entity with the specified name in the same document as the context
node (see [3.3 Unparsed Entities]). It returns the empty string if
there is no such entity.
XML processors may choose to use the System Identifier (if one
is provided) to resolve the entity, rather than the URI in the
Public Identifier. The details are dependent on the processor, and
we would have to support some form of plug-in resolver to handle
this properly. Currently, we simply return the System Identifier if
present, and hope that it a usable URI or that our caller can
map it to one.
TODO: Resolve Public Identifiers... or consider changing function name.
If we find a relative URI
reference, XML expects it to be resolved in terms of the base URI
of the document. The DOM doesn't do that for us, and it isn't
entirely clear whether that should be done here; currently that's
pushed up to a higher level of our application. (Note that DOM Level
1 didn't store the document's base URI.)
TODO: Consider resolving Relative URIs.
(The DOM's statement that "An XML processor may choose to
completely expand entities before the structure model is passed
to the DOM" refers only to parsed entities, not unparsed, and hence
doesn't affect this function.)
String url = "";
if (null == m_entities)
return url;
int n = m_entities.size();
for (int i = 0; i < n; i += ENTITY_FIELDS_PER)
{
String ename = (String) m_entities.elementAt(i + ENTITY_FIELD_NAME);
if (null != ename && ename.equals(name))
{
String nname = (String) m_entities.elementAt(i
+ ENTITY_FIELD_NOTATIONNAME);
if (null != nname)
{
// The draft says: "The XSLT processor may use the public
// identifier to generate a URI for the entity instead of the URI
// specified in the system identifier. If the XSLT processor does
// not use the public identifier to generate the URI, it must use
// the system identifier; if the system identifier is a relative
// URI, it must be resolved into an absolute URI using the URI of
// the resource containing the entity declaration as the base
// URI [RFC2396]."
// So I'm falling a bit short here.
url = (String) m_entities.elementAt(i + ENTITY_FIELD_SYSTEMID);
if (null == url)
{
url = (String) m_entities.elementAt(i + ENTITY_FIELD_PUBLICID);
}
}
break;
}
}
return url;
| public void | ignorableWhitespace(char[] ch, int start, int length)Receive notification of ignorable whitespace in element content.
By default, do nothing. Application writers may override this
method to take specific actions for each chunk of ignorable
whitespace (such as adding data to a node or buffer, or printing
it to a file).
// %OPT% We can probably take advantage of the fact that we know this
// is whitespace.
characters(ch, start, length);
| public void | internalEntityDecl(java.lang.String name, java.lang.String value)Report an internal entity declaration.
Only the effective (first) declaration for each entity
will be reported.
// no op
| public boolean | isAttributeSpecified(int attributeHandle)5. [specified] A flag indicating whether this attribute was actually
specified in the start-tag of its element, or was defaulted from the
DTD.
// I'm not sure if I want to do anything with this...
return true; // ??
| private final boolean | isTextType(int type)Bottleneck determination of text type.
return (DTM.TEXT_NODE == type || DTM.CDATA_SECTION_NODE == type);
| public boolean | isWhitespace(int nodeHandle)Determine if the string-value of a node is whitespace
int identity = makeNodeIdentity(nodeHandle);
int type;
if(identity==DTM.NULL) // Separate lines because I wanted to breakpoint it
type = DTM.NULL;
else
type= _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
int offset = m_data.elementAt(dataIndex);
int length = m_data.elementAt(dataIndex + 1);
return m_chars.isWhitespace(offset, length);
}
return false;
| public void | migrateTo(com.sun.org.apache.xml.internal.dtm.DTMManager manager)Migrate a DTM built with an old DTMManager to a new DTMManager.
After the migration, the new DTMManager will treat the DTM as
one that is built by itself.
This is used to support DTM sharing between multiple transformations.
super.migrateTo(manager);
// We have to reset the information in m_dtmIdent and
// register the DTM with the new manager.
int numDTMs = m_dtmIdent.size();
int dtmId = m_mgrDefault.getFirstFreeDTMID();
int nodeIndex = 0;
for (int i = 0; i < numDTMs; i++)
{
m_dtmIdent.setElementAt(dtmId << DTMManager.IDENT_DTM_NODE_BITS, i);
m_mgrDefault.addDTM(this, dtmId, nodeIndex);
dtmId++;
nodeIndex += (1 << DTMManager.IDENT_DTM_NODE_BITS);
}
| public boolean | needsTwoThreads()
return null != m_incrementalSAXSource;
| protected boolean | nextNode()This method should try and build one or more nodes in the table.
if (null == m_incrementalSAXSource)
return false;
if (m_endDocumentOccured)
{
clearCoRoutine();
return false;
}
Object gotMore = m_incrementalSAXSource.deliverMoreNodes(true);
// gotMore may be a Boolean (TRUE if still parsing, FALSE if
// EOF) or an exception if IncrementalSAXSource malfunctioned
// (code error rather than user error).
//
// %REVIEW% Currently the ErrorHandlers sketched herein are
// no-ops, so I'm going to initially leave this also as a
// no-op.
if (!(gotMore instanceof Boolean))
{
if(gotMore instanceof RuntimeException)
{
throw (RuntimeException)gotMore;
}
else if(gotMore instanceof Exception)
{
throw new WrappedRuntimeException((Exception)gotMore);
}
// for now...
clearCoRoutine();
return false;
// %TBD%
}
if (gotMore != Boolean.TRUE)
{
// EOF reached without satisfying the request
clearCoRoutine(); // Drop connection, stop trying
// %TBD% deregister as its listener?
}
return true;
| public void | notationDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId)Receive notification of a notation declaration.
By default, do nothing. Application writers may override this
method in a subclass if they wish to keep track of the notations
declared in a document.
// no op
| public void | processingInstruction(java.lang.String target, java.lang.String data)Receive notification of a processing instruction.
By default, do nothing. Application writers may override this
method in a subclass to take specific actions for each
processing instruction, such as setting status variables or
invoking other methods.
if (DEBUG)
System.out.println("processingInstruction: target: " + target +", data: "+data);
charactersFlush();
int exName = m_expandedNameTable.getExpandedTypeID(null, target,
DTM.PROCESSING_INSTRUCTION_NODE);
int dataIndex = m_valuesOrPrefixes.stringToIndex(data);
m_previous = addNode(DTM.PROCESSING_INSTRUCTION_NODE, exName,
m_parents.peek(), m_previous,
dataIndex, false);
| public org.xml.sax.InputSource | resolveEntity(java.lang.String publicId, java.lang.String systemId)Resolve an external entity.
Always return null, so that the parser will use the system
identifier provided in the XML document. This method implements
the SAX default behaviour: application writers can override it
in a subclass to do special translations such as catalog lookups
or URI redirection.
return null;
| public void | setDocumentLocator(org.xml.sax.Locator locator)Receive a Locator object for document events.
By default, do nothing. Application writers may override this
method in a subclass if they wish to store the locator for use
with other document events.
m_locator = locator;
m_systemId = locator.getSystemId();
| public void | setIDAttribute(java.lang.String id, int elem)Set an ID string to node association in the ID table.
m_idAttributes.put(id, new Integer(elem));
| public void | setIncrementalSAXSource(com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource incrementalSAXSource)Bind a IncrementalSAXSource to this DTM. If we discover we need nodes
that have not yet been built, we will ask this object to send us more
events, and it will manage interactions with its data sources.
Note that we do not actually build the IncrementalSAXSource, since we don't
know what source it's reading from, what thread that source will run in,
or when it will run.
// Establish coroutine link so we can request more data
//
// Note: It's possible that some versions of IncrementalSAXSource may
// not actually use a CoroutineManager, and hence may not require
// that we obtain an Application Coroutine ID. (This relies on the
// coroutine transaction details having been encapsulated in the
// IncrementalSAXSource.do...() methods.)
m_incrementalSAXSource = incrementalSAXSource;
// Establish SAX-stream link so we can receive the requested data
incrementalSAXSource.setContentHandler(this);
incrementalSAXSource.setLexicalHandler(this);
incrementalSAXSource.setDTDHandler(this);
// Are the following really needed? incrementalSAXSource doesn't yet
// support them, and they're mostly no-ops here...
//incrementalSAXSource.setErrorHandler(this);
//incrementalSAXSource.setDeclHandler(this);
| public void | setProperty(java.lang.String property, java.lang.Object value)Set a run time property for this DTM instance.
%REVIEW% Now that we no longer use this method to support
getSourceLocatorFor, can we remove it?
| protected void | setSourceLocation()Store the source location of the current node. This method must be called
as every node is added to the DTM or for no node.
m_sourceSystemId.addElement(m_locator.getSystemId());
m_sourceLine.addElement(m_locator.getLineNumber());
m_sourceColumn.addElement(m_locator.getColumnNumber());
//%REVIEW% %BUG% Prevent this from arising in the first place
// by not allowing the enabling conditions to change after we start
// building the document.
if (m_sourceSystemId.size() != m_size) {
System.err.println("CODING ERROR in Source Location: " + m_size
+ " != "
+ m_sourceSystemId.size());
System.exit(1);
}
| public static void | setUseSourceLocation(boolean useSourceLocation)Set whether information about document source location
should be maintained or not.
m_source_location = useSourceLocation;
| public void | skippedEntity(java.lang.String name)Receive notification of a skipped entity.
By default, do nothing. Application writers may override this
method in a subclass to take specific actions for each
processing instruction, such as setting status variables or
invoking other methods.
// %REVIEW% What should be done here?
// no op
| public void | startCDATA()Report the start of a CDATA section.
The contents of the CDATA section will be reported through
the regular {@link org.xml.sax.ContentHandler#characters
characters} event.
m_textType = DTM.CDATA_SECTION_NODE;
| public void | startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)Report the start of DTD declarations, if any.
Any declarations are assumed to be in the internal subset
unless otherwise indicated by a {@link #startEntity startEntity}
event.
Note that the start/endDTD events will appear within
the start/endDocument events from ContentHandler and
before the first startElement event.
m_insideDTD = true;
| public void | startDocument()Receive notification of the beginning of the document.
if (DEBUG)
System.out.println("startDocument");
int doc = addNode(DTM.DOCUMENT_NODE,
m_expandedNameTable.getExpandedTypeID(DTM.DOCUMENT_NODE),
DTM.NULL, DTM.NULL, 0, true);
m_parents.push(doc);
m_previous = DTM.NULL;
m_contextIndexes.push(m_prefixMappings.size()); // for the next element.
| public void | startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, org.xml.sax.Attributes attributes)Receive notification of the start of an element.
By default, do nothing. Application writers may override this
method in a subclass to take specific actions at the start of
each element (such as allocating a new tree node or writing
output to a file).
if (DEBUG)
{
System.out.println("startElement: uri: " + uri + ", localname: "
+ localName + ", qname: "+qName+", atts: " + attributes);
boolean DEBUG_ATTRS=true;
if(DEBUG_ATTRS & attributes!=null)
{
int n = attributes.getLength();
if(n==0)
System.out.println("\tempty attribute list");
else for (int i = 0; i < n; i++)
System.out.println("\t attr: uri: " + attributes.getURI(i) +
", localname: " + attributes.getLocalName(i) +
", qname: " + attributes.getQName(i) +
", type: " + attributes.getType(i) +
", value: " + attributes.getValue(i)
);
}
}
charactersFlush();
int exName = m_expandedNameTable.getExpandedTypeID(uri, localName, DTM.ELEMENT_NODE);
String prefix = getPrefix(qName, uri);
int prefixIndex = (null != prefix)
? m_valuesOrPrefixes.stringToIndex(qName) : 0;
int elemNode = addNode(DTM.ELEMENT_NODE, exName,
m_parents.peek(), m_previous, prefixIndex, true);
if(m_indexing)
indexNode(exName, elemNode);
m_parents.push(elemNode);
int startDecls = m_contextIndexes.peek();
int nDecls = m_prefixMappings.size();
int prev = DTM.NULL;
if(!m_pastFirstElement)
{
// SPECIAL CASE: Implied declaration at root element
prefix="xml";
String declURL = "http://www.w3.org/XML/1998/namespace";
exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
int val = m_valuesOrPrefixes.stringToIndex(declURL);
prev = addNode(DTM.NAMESPACE_NODE, exName, elemNode,
prev, val, false);
m_pastFirstElement=true;
}
for (int i = startDecls; i < nDecls; i += 2)
{
prefix = (String) m_prefixMappings.elementAt(i);
if (prefix == null)
continue;
String declURL = (String) m_prefixMappings.elementAt(i + 1);
exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
int val = m_valuesOrPrefixes.stringToIndex(declURL);
prev = addNode(DTM.NAMESPACE_NODE, exName, elemNode,
prev, val, false);
}
int n = attributes.getLength();
for (int i = 0; i < n; i++)
{
String attrUri = attributes.getURI(i);
String attrQName = attributes.getQName(i);
String valString = attributes.getValue(i);
prefix = getPrefix(attrQName, attrUri);
int nodeType;
String attrLocalName = attributes.getLocalName(i);
if ((null != attrQName)
&& (attrQName.equals("xmlns")
|| attrQName.startsWith("xmlns:")))
{
if (declAlreadyDeclared(prefix))
continue; // go to the next attribute.
nodeType = DTM.NAMESPACE_NODE;
}
else
{
nodeType = DTM.ATTRIBUTE_NODE;
if (attributes.getType(i).equalsIgnoreCase("ID"))
setIDAttribute(valString, elemNode);
}
// Bit of a hack... if somehow valString is null, stringToIndex will
// return -1, which will make things very unhappy.
if(null == valString)
valString = "";
int val = m_valuesOrPrefixes.stringToIndex(valString);
//String attrLocalName = attributes.getLocalName(i);
if (null != prefix)
{
prefixIndex = m_valuesOrPrefixes.stringToIndex(attrQName);
int dataIndex = m_data.size();
m_data.addElement(prefixIndex);
m_data.addElement(val);
val = -dataIndex;
}
exName = m_expandedNameTable.getExpandedTypeID(attrUri, attrLocalName, nodeType);
prev = addNode(nodeType, exName, elemNode, prev, val,
false);
}
if (DTM.NULL != prev)
m_nextsib.setElementAt(DTM.NULL,prev);
if (null != m_wsfilter)
{
short wsv = m_wsfilter.getShouldStripSpace(makeNodeHandle(elemNode), this);
boolean shouldStrip = (DTMWSFilter.INHERIT == wsv)
? getShouldStripWhitespace()
: (DTMWSFilter.STRIP == wsv);
pushShouldStripWhitespace(shouldStrip);
}
m_previous = DTM.NULL;
m_contextIndexes.push(m_prefixMappings.size()); // for the children.
| public void | startEntity(java.lang.String name)Report the beginning of an entity in content.
NOTE: entity references in attribute
values -- and the start and end of the document entity --
are never reported.
The start and end of the external DTD subset are reported
using the pseudo-name "[dtd]". All other events must be
properly nested within start/end entity events.
Note that skipped entities will be reported through the
{@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
event, which is part of the ContentHandler interface.
// no op
| public void | startPrefixMapping(java.lang.String prefix, java.lang.String uri)Receive notification of the start of a Namespace mapping.
By default, do nothing. Application writers may override this
method in a subclass to take specific actions at the start of
each Namespace prefix scope (such as storing the prefix mapping).
if (DEBUG)
System.out.println("startPrefixMapping: prefix: " + prefix + ", uri: "
+ uri);
if(null == prefix)
prefix = "";
m_prefixMappings.addElement(prefix); // JDK 1.1.x compat -sc
m_prefixMappings.addElement(uri); // JDK 1.1.x compat -sc
| public void | unparsedEntityDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId, java.lang.String notationName)Receive notification of an unparsed entity declaration.
By default, do nothing. Application writers may override this
method in a subclass to keep track of the unparsed entities
declared in a document.
if (null == m_entities)
{
m_entities = new Vector();
}
try
{
systemId = SystemIDResolver.getAbsoluteURI(systemId,
getDocumentBaseURI());
}
catch (Exception e)
{
throw new org.xml.sax.SAXException(e);
}
// private static final int ENTITY_FIELD_PUBLICID = 0;
m_entities.addElement(publicId);
// private static final int ENTITY_FIELD_SYSTEMID = 1;
m_entities.addElement(systemId);
// private static final int ENTITY_FIELD_NOTATIONNAME = 2;
m_entities.addElement(notationName);
// private static final int ENTITY_FIELD_NAME = 3;
m_entities.addElement(name);
| public void | warning(org.xml.sax.SAXParseException e)Receive notification of a parser warning.
The default implementation does nothing. Application writers
may override this method in a subclass to take specific actions
for each warning, such as inserting the message in a log file or
printing it to the console.
// %REVIEW% Is there anyway to get the JAXP error listener here?
System.err.println(e.getMessage());
|
|