getDocument
method. The actual pipeline is defined in
* parser configuration.
*
* @author Arnaud Le Hors, IBM
* @author Andy Clark, IBM
* @author Elena Litani, IBM
*
* @version $Id: AbstractDOMParser.java,v 1.108 2004/02/17 07:14:48 neeraj Exp $
*/
public class AbstractDOMParser extends AbstractXMLDocumentParser {
//
// Constants
//
// feature ids
/** Feature id: namespace. */
protected static final String NAMESPACES =
Constants.SAX_FEATURE_PREFIX+Constants.NAMESPACES_FEATURE;
/** Feature id: create entity ref nodes. */
protected static final String CREATE_ENTITY_REF_NODES =
Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
/** Feature id: include comments. */
protected static final String INCLUDE_COMMENTS_FEATURE =
Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_COMMENTS_FEATURE;
/** Feature id: create cdata nodes. */
protected static final String CREATE_CDATA_NODES_FEATURE =
Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE;
/** Feature id: include ignorable whitespace. */
protected static final String INCLUDE_IGNORABLE_WHITESPACE =
Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_IGNORABLE_WHITESPACE;
/** Feature id: defer node expansion. */
protected static final String DEFER_NODE_EXPANSION =
Constants.XERCES_FEATURE_PREFIX + Constants.DEFER_NODE_EXPANSION_FEATURE;
/** Recognized features. */
private static final String[] RECOGNIZED_FEATURES = {
NAMESPACES,
CREATE_ENTITY_REF_NODES,
INCLUDE_COMMENTS_FEATURE,
CREATE_CDATA_NODES_FEATURE,
INCLUDE_IGNORABLE_WHITESPACE,
DEFER_NODE_EXPANSION
};
// property ids
/** Property id: document class name. */
protected static final String DOCUMENT_CLASS_NAME =
Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_CLASS_NAME_PROPERTY;
protected static final String CURRENT_ELEMENT_NODE=
Constants.XERCES_PROPERTY_PREFIX + Constants.CURRENT_ELEMENT_NODE_PROPERTY;
// protected static final String GRAMMAR_POOL =
// Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
/** Recognized properties. */
private static final String[] RECOGNIZED_PROPERTIES = {
DOCUMENT_CLASS_NAME,
CURRENT_ELEMENT_NODE,
};
// other
/** Default document class name. */
protected static final String DEFAULT_DOCUMENT_CLASS_NAME =
"com.sun.org.apache.xerces.internal.dom.DocumentImpl";
protected static final String CORE_DOCUMENT_CLASS_NAME =
"com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl";
protected static final String PSVI_DOCUMENT_CLASS_NAME =
"com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl";
/**
* If the user stops the process, this exception will be thrown.
*/
public static final RuntimeException abort = new RuntimeException();
// debugging
private static final boolean DEBUG_EVENTS = false;
private static final boolean DEBUG_BASEURI = false;
//
// Data
//
/** DOM L3 error handler */
protected DOMErrorHandlerWrapper fErrorHandler = null;
/** True if inside DTD. */
protected boolean fInDTD;
// features
/** Create entity reference nodes. */
protected boolean fCreateEntityRefNodes;
/** Include ignorable whitespace. */
protected boolean fIncludeIgnorableWhitespace;
/** Include Comments. */
protected boolean fIncludeComments;
/** Create cdata nodes. */
protected boolean fCreateCDATANodes;
// dom information
/** The document. */
protected Document fDocument;
/** The default Xerces document implementation, if used. */
protected CoreDocumentImpl fDocumentImpl;
/** Whether to store PSVI information in DOM tree. */
protected boolean fStorePSVI;
/** The document class name to use. */
protected String fDocumentClassName;
/** The document type node. */
protected DocumentType fDocumentType;
/** Current node. */
protected Node fCurrentNode;
protected CDATASection fCurrentCDATASection;
protected EntityImpl fCurrentEntityDecl;
protected int fDeferredEntityDecl;
/** Character buffer */
protected final StringBuffer fStringBuffer = new StringBuffer (50);
// internal subset
/** Internal subset buffer. */
protected StringBuffer fInternalSubset;
// deferred expansion data
protected boolean fDeferNodeExpansion;
protected boolean fNamespaceAware;
protected DeferredDocumentImpl fDeferredDocumentImpl;
protected int fDocumentIndex;
protected int fDocumentTypeIndex;
protected int fCurrentNodeIndex;
protected int fCurrentCDATASectionIndex;
// state
/** True if inside DTD external subset. */
protected boolean fInDTDExternalSubset;
/** Root element name */
protected QName fRoot = new QName();
/** True if inside CDATA section. */
protected boolean fInCDATASection;
/** True if saw the first chunk of characters*/
protected boolean fFirstChunk = false;
/** LSParserFilter: specifies that element with given QNAME and all its children
must be rejected */
protected boolean fFilterReject = false;
// data
/** Base uri stack*/
protected Stack fBaseURIStack = new Stack ();
/** LSParserFilter: the QNAME of rejected element*/
protected final QName fRejectedElement = new QName ();
/** LSParserFilter: store qnames of skipped elements*/
protected Stack fSkippedElemStack = null;
/** LSParserFilter: true if inside entity reference */
protected boolean fInEntityRef = false;
/** Attribute QName. */
private QName fAttrQName = new QName ();
// handlers
protected LSParserFilter fDOMFilter = null;
//
// Constructors
//
/** Default constructor. */
protected AbstractDOMParser (XMLParserConfiguration config) {
super (config);
// add recognized features
fConfiguration.addRecognizedFeatures (RECOGNIZED_FEATURES);
// set default values
fConfiguration.setFeature (CREATE_ENTITY_REF_NODES, true);
fConfiguration.setFeature (INCLUDE_IGNORABLE_WHITESPACE, true);
fConfiguration.setFeature (DEFER_NODE_EXPANSION, true);
fConfiguration.setFeature (INCLUDE_COMMENTS_FEATURE, true);
fConfiguration.setFeature (CREATE_CDATA_NODES_FEATURE, true);
// add recognized properties
fConfiguration.addRecognizedProperties (RECOGNIZED_PROPERTIES);
// set default values
fConfiguration.setProperty (DOCUMENT_CLASS_NAME,
DEFAULT_DOCUMENT_CLASS_NAME);
} // * Note: This method is not called for entity references * appearing as part of attribute values. * * @param name The name of the general entity. * @param identifier The resource identifier. * @param encoding The auto-detected IANA encoding name of the entity * stream. This value will be null in those situations * where the entity encoding is not auto-detected (e.g. * internal entities or a document entity that is * parsed from a java.io.Reader). * @param augs Additional information that may include infoset augmentations * * @exception XNIException Thrown by handler to signal an error. */ public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException { if (DEBUG_EVENTS) { System.out.println("==>startGeneralEntity ("+name+")"); if (DEBUG_BASEURI) { System.out.println(" expandedSystemId( **baseURI): "+identifier.getExpandedSystemId()); System.out.println(" baseURI:"+ identifier.getBaseSystemId()); } } // Always create entity reference nodes to be able to recreate // entity as a part of doctype if (!fDeferNodeExpansion) { if (fFilterReject) { return; } setCharacterData(true); EntityReference er = fDocument.createEntityReference(name); if (fDocumentImpl != null) { // REVISIT: baseURI/actualEncoding // remove dependency on our implementation when DOM L3 is REC // EntityReferenceImpl erImpl =(EntityReferenceImpl)er; // set base uri erImpl.setBaseURI(identifier.getExpandedSystemId()); if (fDocumentType != null) { // set actual encoding NamedNodeMap entities = fDocumentType.getEntities(); fCurrentEntityDecl = (EntityImpl) entities.getNamedItem(name); if (fCurrentEntityDecl != null) { fCurrentEntityDecl.setInputEncoding(encoding); } } // we don't need synchronization now, because entity ref will be // expanded anyway. Synch only needed when user creates entityRef node erImpl.needsSyncChildren(false); } fInEntityRef = true; fCurrentNode.appendChild (er); fCurrentNode = er; } else { int er = fDeferredDocumentImpl.createDeferredEntityReference(name, identifier.getExpandedSystemId()); if (fDocumentTypeIndex != -1) { // find corresponding Entity decl int node = fDeferredDocumentImpl.getLastChild(fDocumentTypeIndex, false); while (node != -1) { short nodeType = fDeferredDocumentImpl.getNodeType(node, false); if (nodeType == Node.ENTITY_NODE) { String nodeName = fDeferredDocumentImpl.getNodeName(node, false); if (nodeName.equals(name)) { fDeferredEntityDecl = node; fDeferredDocumentImpl.setInputEncoding(node, encoding); break; } } node = fDeferredDocumentImpl.getRealPrevSibling(node, false); } } fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, er); fCurrentNodeIndex = er; } } // startGeneralEntity(String,XMLResourceIdentifier, Augmentations) /** * Notifies of the presence of a TextDecl line in an entity. If present, * this method will be called immediately following the startEntity call. *
* Note: This method will never be called for the * document entity; it is only called for external general entities * referenced in document content. *
* Note: This method is not called for entity references * appearing as part of attribute values. * * @param version The XML version, or null if not specified. * @param encoding The IANA encoding name of the entity. * @param augs Additional information that may include infoset augmentations * * @throws XNIException Thrown by handler to signal an error. */ public void textDecl(String version, String encoding, Augmentations augs) throws XNIException { if (fInDTD){ return; } if (!fDeferNodeExpansion) { if (fCurrentEntityDecl != null && !fFilterReject) { fCurrentEntityDecl.setXmlEncoding(encoding); if(version != null) fCurrentEntityDecl.setXmlVersion(version); } } else { if (fDeferredEntityDecl !=-1) { fDeferredDocumentImpl.setEntityInfo(fDeferredEntityDecl, version, encoding); } } } // textDecl(String,String) /** * A comment. * * @param text The text in the comment. * @param augs Additional information that may include infoset augmentations * * @throws XNIException Thrown by application to signal an error. */ public void comment(XMLString text, Augmentations augs) throws XNIException { if (fInDTD) { if (fInternalSubset != null && !fInDTDExternalSubset) { fInternalSubset.append(""); } return; } if (!fIncludeComments || fFilterReject) { return; } if (!fDeferNodeExpansion) { Comment comment = fDocument.createComment (text.toString ()); setCharacterData (false); fCurrentNode.appendChild (comment); if (fDOMFilter !=null && !fInEntityRef && (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_COMMENT)!= 0) { short code = fDOMFilter.acceptNode (comment); switch (code) { case LSParserFilter.FILTER_INTERRUPT:{ throw abort; } case LSParserFilter.FILTER_REJECT:{ // REVISIT: the constant FILTER_REJECT should be changed when new // DOM LS specs gets published // fall through to SKIP since comment has no children. } case LSParserFilter.FILTER_SKIP: { // REVISIT: the constant FILTER_SKIP should be changed when new // DOM LS specs gets published fCurrentNode.removeChild(comment); // make sure we don't loose chars if next event is characters() fFirstChunk = true; return; } default: { // accept node } } } } else { int comment = fDeferredDocumentImpl.createDeferredComment(text.toString()); fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, comment); } } // comment(XMLString) /** * A processing instruction. Processing instructions consist of a * target name and, optionally, text data. The data is only meaningful * to the application. *
* Typically, a processing instruction's data will contain a series
* of pseudo-attributes. These pseudo-attributes follow the form of
* element attributes but are not parsed or presented
* to the application as anything other than text. The application is
* responsible for parsing the data.
*
* @param target The target.
* @param data The data or null if none specified.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void processingInstruction (String target, XMLString data, Augmentations augs)
throws XNIException {
if (fInDTD) {
if (fInternalSubset != null && !fInDTDExternalSubset) {
fInternalSubset.append ("");
fInternalSubset.append (target.toString ());
fInternalSubset.append (' ');
fInternalSubset.append (data.toString ());
fInternalSubset.append ("?>");
}
return;
}
if (DEBUG_EVENTS) {
System.out.println ("==>processingInstruction ("+target+")");
}
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
ProcessingInstruction pi =
fDocument.createProcessingInstruction (target, data.toString ());
setCharacterData (false);
fCurrentNode.appendChild (pi);
if (fDOMFilter !=null && !fInEntityRef &&
(fDOMFilter.getWhatToShow () & NodeFilter.SHOW_PROCESSING_INSTRUCTION)!= 0) {
short code = fDOMFilter.acceptNode (pi);
switch (code) {
case LSParserFilter.FILTER_INTERRUPT:{
throw abort;
}
case LSParserFilter.FILTER_REJECT:{
// fall through to SKIP since PI has no children.
}
case LSParserFilter.FILTER_SKIP: {
fCurrentNode.removeChild(pi);
// fFirstChunk must be set to true so that data
// won't be lost in the case where the child before PI is
// a text node and the next event is characters.
fFirstChunk = true;
return;
}
default: {
}
}
}
}
else {
int pi = fDeferredDocumentImpl.
createDeferredProcessingInstruction(target, data.toString());
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, pi);
}
} // processingInstruction(String,XMLString)
/**
* The start of the document.
*
* @param locator The system identifier of the entity if the entity
* is external, null otherwise.
* @param encoding The auto-detected IANA encoding name of the entity
* stream. This value will be null in those situations
* where the entity encoding is not auto-detected (e.g.
* internal entities or a document entity that is
* parsed from a java.io.Reader).
* @param namespaceContext
* The namespace context in effect at the
* start of this document.
* This object represents the current context.
* Implementors of this class are responsible
* for copying the namespace bindings from the
* the current context (and its parent contexts)
* if that information is important.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void startDocument (XMLLocator locator, String encoding,
NamespaceContext namespaceContext, Augmentations augs)
throws XNIException {
if (!fDeferNodeExpansion) {
if (fDocumentClassName.equals (DEFAULT_DOCUMENT_CLASS_NAME)) {
fDocument = new DocumentImpl ();
fDocumentImpl = (CoreDocumentImpl)fDocument;
// REVISIT: when DOM Level 3 is REC rely on Document.support
// instead of specific class
// set DOM error checking off
fDocumentImpl.setStrictErrorChecking (false);
// set actual encoding
fDocumentImpl.setInputEncoding (encoding);
// set documentURI
fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
}
else if (fDocumentClassName.equals (PSVI_DOCUMENT_CLASS_NAME)) {
fDocument = new PSVIDocumentImpl();
fDocumentImpl = (CoreDocumentImpl)fDocument;
fStorePSVI = true;
// REVISIT: when DOM Level 3 is REC rely on Document.support
// instead of specific class
// set DOM error checking off
fDocumentImpl.setStrictErrorChecking (false);
// set actual encoding
fDocumentImpl.setInputEncoding (encoding);
// set documentURI
fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
}
else {
// use specified document class
try {
ClassLoader cl = ObjectFactory.findClassLoader();
Class documentClass = ObjectFactory.findProviderClass (fDocumentClassName,
cl, true);
fDocument = (Document)documentClass.newInstance ();
// if subclass of our own class that's cool too
Class defaultDocClass =
ObjectFactory.findProviderClass (CORE_DOCUMENT_CLASS_NAME,
cl, true);
if (defaultDocClass.isAssignableFrom (documentClass)) {
fDocumentImpl = (CoreDocumentImpl)fDocument;
Class psviDocClass = ObjectFactory.findProviderClass (PSVI_DOCUMENT_CLASS_NAME,
cl, true);
if (psviDocClass.isAssignableFrom (documentClass)) {
fStorePSVI = true;
}
// REVISIT: when DOM Level 3 is REC rely on
// Document.support instead of specific class
// set DOM error checking off
fDocumentImpl.setStrictErrorChecking(false);
// set actual encoding
fDocumentImpl.setInputEncoding(encoding);
// set documentURI
if (locator != null) {
fDocumentImpl.setDocumentURI(locator.getExpandedSystemId());
}
}
}
catch (ClassNotFoundException e) {
// won't happen we already checked that earlier
}
catch (Exception e) {
throw new RuntimeException (
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"CannotCreateDocumentClass",
new Object [] {fDocumentClassName}));
}
}
fCurrentNode = fDocument;
}
else {
fDeferredDocumentImpl = new DeferredDocumentImpl(fNamespaceAware);
fDocument = fDeferredDocumentImpl;
fDocumentIndex = fDeferredDocumentImpl.createDeferredDocument();
// REVISIT: strict error checking is not implemented in deferred dom.
// Document.support instead of specific class
// set actual encoding
fDeferredDocumentImpl.setInputEncoding(encoding);
// set documentURI
fDeferredDocumentImpl.setDocumentURI(locator.getExpandedSystemId());
fCurrentNodeIndex = fDocumentIndex;
}
} // startDocument(String,String)
/**
* Notifies of the presence of an XMLDecl line in the document. If
* present, this method will be called immediately following the
* startDocument call.
*
* @param version The XML version.
* @param encoding The IANA encoding name of the document, or null if
* not specified.
* @param standalone The standalone value, or null if not specified.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void xmlDecl(String version, String encoding, String standalone,
Augmentations augs)
throws XNIException {
if (!fDeferNodeExpansion) {
// REVISIT: when DOM Level 3 is REC rely on Document.support
// instead of specific class
if (fDocumentImpl != null) {
if(version != null)
fDocumentImpl.setXmlVersion(version);
fDocumentImpl.setXmlEncoding(encoding);
fDocumentImpl.setXmlStandalone("yes".equals(standalone));
}
}
else {
if(version != null)
fDeferredDocumentImpl.setXmlVersion(version);
fDeferredDocumentImpl.setXmlEncoding(encoding);
fDeferredDocumentImpl.setXmlStandalone("yes".equals(standalone));
}
} // xmlDecl(String,String,String)
/**
* Notifies of the presence of the DOCTYPE line in the document.
*
* @param rootElement The name of the root element.
* @param publicId The public identifier if an external DTD or null
* if the external DTD is specified using SYSTEM.
* @param systemId The system identifier if an external DTD, null
* otherwise.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void doctypeDecl (String rootElement,
String publicId, String systemId, Augmentations augs)
throws XNIException {
if (!fDeferNodeExpansion) {
if (fDocumentImpl != null) {
fDocumentType = fDocumentImpl.createDocumentType(
rootElement, publicId, systemId);
fCurrentNode.appendChild(fDocumentType);
}
}
else {
fDocumentTypeIndex = fDeferredDocumentImpl.
createDeferredDocumentType(rootElement, publicId, systemId);
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, fDocumentTypeIndex);
}
} // doctypeDecl(String,String,String)
/**
* The start of an element. If the document specifies the start element
* by using an empty tag, then the startElement method will immediately
* be followed by the endElement method, with no intervening methods.
*
* @param element The name of the element.
* @param attributes The element attributes.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>startElement ("+element.rawname+")");
}
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
Element el = createElementNode(element);
int attrCount = attributes.getLength();
for (int i = 0; i < attrCount; i++) {
attributes.getName (i, fAttrQName);
Attr attr = createAttrNode (fAttrQName);
String attrValue = attributes.getValue (i);
Augmentations aaugs = attributes.getAugmentations(i);
AttributePSVI attrPSVI =(AttributePSVI) aaugs.getItem(Constants.ATTRIBUTE_PSVI);
if (fStorePSVI && attrPSVI != null){
((PSVIAttrNSImpl) attr).setPSVI (attrPSVI);
}
attr.setValue(attrValue);
el.setAttributeNode(attr);
// NOTE: The specified value MUST be set after you set
// the node value because that turns the "specified"
// flag to "true" which may overwrite a "false"
// value from the attribute list. -Ac
if (fDocumentImpl != null) {
AttrImpl attrImpl = (AttrImpl)attr;
attrImpl.setType(getAttributeType(attributes,aaugs,i));
if (isIdAttribute(attributes,aaugs,i)) {
((ElementImpl)el).setIdAttributeNode(attr, true);
}
attrImpl.setSpecified(attributes.isSpecified(i));
// REVISIT: Handle entities in attribute value.
}
}
setCharacterData (false);
((ElementImpl)el).setType(getElementTypeInfoFromAugs(augs));
// filter nodes
if (fDOMFilter != null && !fInEntityRef) {
if (fRoot.rawname == null) {
// fill value of the root element
fRoot.setValues(element);
} else {
short code = fDOMFilter.startElement(el);
switch (code) {
case LSParserFilter.FILTER_INTERRUPT :
{
throw abort;
}
case LSParserFilter.FILTER_REJECT :
{
fFilterReject = true;
fRejectedElement.setValues(element);
return;
}
case LSParserFilter.FILTER_SKIP :
{
fSkippedElemStack.push(new QName(element));
return;
}
default : {}
}
}
}
fCurrentNode.appendChild (el);
fCurrentNode = el;
}
else {
int el =
fDeferredDocumentImpl.createDeferredElement(fNamespaceAware ?
element.uri : null,
element.rawname,
getElementTypeInfoFromAugs(augs));
int attrCount = attributes.getLength();
for (int i = 0; i < attrCount; i++) {
// set type information
Augmentations aaugs = attributes.getAugmentations(i);
// create attribute
fDeferredDocumentImpl.setDeferredAttribute(
el,
attributes.getQName(i),
attributes.getURI(i),
attributes.getValue(i),
attributes.isSpecified(i),
isIdAttribute(attributes,aaugs,i),
getAttributeType(attributes,aaugs,i));
}
fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, el);
fCurrentNodeIndex = el;
}
} // startElement(QName,XMLAttributes)
/**
* Returns true if the given attribute is marked as ID.
*/
private boolean isIdAttribute(XMLAttributes attributes,Augmentations augs, int index) {
// look for augmentation first.
Object o = augs.getItem(Constants.ID_ATTRIBUTE);
if( o instanceof Boolean )
return ((Boolean)o).booleanValue();
// otherwise fall back to the DTD mode.
return "ID".equals(attributes.getType(index));
}
/**
* Returns {@link TypeInfo} for the given attribute.
*/
private TypeInfo getAttributeType(XMLAttributes attributes,Augmentations augs, int index) {
// look for augmentation
TypeInfo type = (TypeInfo)augs.getItem(Constants.TYPEINFO);
if(type!=null) return type;
boolean isDeclared = Boolean.TRUE.equals (attributes.getAugmentations (index).getItem (Constants.ATTRIBUTE_DECLARED));
// otherwise fall back to the DTD mode.
if (isDeclared )
return TypeInfoImpl.getDTDTypeInfo(attributes.getType(index));
else
return new TypeInfoImpl();
}
/**
* Looks for {@link TypeInfo} object for the element in the augmentation.
*
* @return null if not found.
*/
private TypeInfo getElementTypeInfoFromAugs( Augmentations augs ) {
//simple fix to handle dtd case.
if (augs == null) return new TypeInfoImpl();
// if an external validator is used via JAXP, this would be set.
TypeInfo ti = (TypeInfo)augs.getItem(Constants.TYPEINFO);
if(ti!=null) return ti;
// Xerces native validator would set this.
ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
if (elementPSVI == null) return null;
XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
if( type!=null ) return type;
return elementPSVI.getTypeDefinition();
}
// /**
// * Looks for {@link TypeInfo} object for the attribute in the augmentation.
// */
// private TypeInfo getAttribtueTypeInfoFromAugs( XMLAttributes atts, int idx ) {
// Augmentations augs = atts.getAugmentations(idx);
//
// // if an external validator is used via JAXP, this would be set.
// TypeInfo type = (TypeInfo)augs.getItem(Constants.TYPEINFO);
// if(type!=null) return type;
//
// // look for PSVI
// AttributePSVI attrPSVI =(AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI);
// if (attrPSVI != null) {
// type = attrPSVI.getMemberTypeDefinition();
// if (type == null)
// type = attrPSVI.getTypeDefinition();
//
// return type;
// }
//
// // if everything else fails, fall back to the DTD type.
// String typeName = atts.getType(idx);
// return new TypeInfoImpl(null, typeName);
// }
/**
* An empty element.
*
* @param element The name of the element.
* @param attributes The element attributes.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void emptyElement (QName element, XMLAttributes attributes, Augmentations augs)
throws XNIException {
startElement (element, attributes, augs);
endElement (element, augs);
} // emptyElement(QName,XMLAttributes)
/**
* Character content.
*
* @param text The content.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void characters (XMLString text, Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>characters(): "+text.toString());
}
if (!fDeferNodeExpansion) {
if (fFilterReject) {
return;
}
if (fInCDATASection && fCreateCDATANodes) {
if (fCurrentCDATASection == null) {
fCurrentCDATASection =
fDocument.createCDATASection(text.toString());
fCurrentNode.appendChild(fCurrentCDATASection);
fCurrentNode = fCurrentCDATASection;
}
else {
fCurrentCDATASection.appendData(text.toString());
}
}
else if (!fInDTD) {
// if type is union (XML Schema) it is possible that we receive
// character call with empty data
if (text.length == 0) {
return;
}
String value = text.toString ();
Node child = fCurrentNode.getLastChild ();
if (child != null && child.getNodeType () == Node.TEXT_NODE) {
// collect all the data into the string buffer.
if (fFirstChunk) {
if (fDocumentImpl != null) {
fStringBuffer.append(((TextImpl)child).removeData());
} else {
fStringBuffer.append(((Text)child).getData());
((Text)child).setNodeValue(null);
}
fFirstChunk = false;
}
fStringBuffer.append(value);
}
else {
fFirstChunk = true;
Text textNode = fDocument.createTextNode(value);
fCurrentNode.appendChild(textNode);
}
}
}
else {
// The Text and CDATASection normalization is taken care of within
// the DOM in the deferred case.
if (fInCDATASection && fCreateCDATANodes) {
if (fCurrentCDATASectionIndex == -1) {
int cs = fDeferredDocumentImpl.
createDeferredCDATASection (text.toString ());
fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, cs);
fCurrentCDATASectionIndex = cs;
fCurrentNodeIndex = cs;
}
else {
int txt = fDeferredDocumentImpl.
createDeferredTextNode(text.toString(), false);
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
}
} else if (!fInDTD) {
// if type is union (XML Schema) it is possible that we receive
// character call with empty data
if (text.length == 0) {
return;
}
String value = text.toString ();
int txt = fDeferredDocumentImpl.
createDeferredTextNode (value, false);
fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, txt);
}
}
} // characters(XMLString)
/**
* Ignorable whitespace. For this method to be called, the document
* source must have some way of determining that the text containing
* only whitespace characters should be considered ignorable. For
* example, the validator can determine if a length of whitespace
* characters in the document are ignorable based on the element
* content model.
*
* @param text The ignorable whitespace.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void ignorableWhitespace (XMLString text, Augmentations augs) throws XNIException {
if (!fIncludeIgnorableWhitespace || fFilterReject) {
return;
}
if (!fDeferNodeExpansion) {
Node child = fCurrentNode.getLastChild();
if (child != null && child.getNodeType() == Node.TEXT_NODE) {
Text textNode = (Text)child;
textNode.appendData(text.toString());
}
else {
Text textNode = fDocument.createTextNode(text.toString());
if (fDocumentImpl != null) {
TextImpl textNodeImpl = (TextImpl)textNode;
textNodeImpl.setIgnorableWhitespace(true);
}
fCurrentNode.appendChild(textNode);
}
}
else {
// The Text normalization is taken care of within the DOM in the
// deferred case.
int txt = fDeferredDocumentImpl.
createDeferredTextNode(text.toString(), true);
fDeferredDocumentImpl.appendChild(fCurrentNodeIndex, txt);
}
} // ignorableWhitespace(XMLString)
/**
* The end of an element.
*
* @param element The name of the element.
* @param augs Additional information that may include infoset augmentations
*
* @throws XNIException Thrown by handler to signal an error.
*/
public void endElement(QName element, Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>endElement ("+element.rawname+")");
}
if (!fDeferNodeExpansion) {
// REVISIT: Should this happen after we call the filter?
if (fStorePSVI && augs != null) {
ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
if (elementPSVI != null) {
((PSVIElementNSImpl)fCurrentNode).setPSVI(elementPSVI);
}
}
if (fDOMFilter != null) {
if (fFilterReject) {
if (element.equals(fRejectedElement)) {
fFilterReject = false;
}
return;
}
if (!fSkippedElemStack.isEmpty()) {
if (fSkippedElemStack.peek().equals(element)) {
fSkippedElemStack.pop();
return;
}
}
setCharacterData (false);
if (!fRoot.equals(element) && !fInEntityRef && (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_ELEMENT)!=0) {
short code = fDOMFilter.acceptNode (fCurrentNode);
switch (code) {
case LSParserFilter.FILTER_INTERRUPT:{
throw abort;
}
case LSParserFilter.FILTER_REJECT:{
Node parent = fCurrentNode.getParentNode();
parent.removeChild(fCurrentNode);
fCurrentNode = parent;
return;
}
case LSParserFilter.FILTER_SKIP: {
// make sure that if any char data is available
// the fFirstChunk is true, so that if the next event
// is characters(), and the last node is text, we will copy
// the value already in the text node to fStringBuffer
// (not to loose it).
fFirstChunk = true;
// replace children
Node parent = fCurrentNode.getParentNode ();
NodeList ls = fCurrentNode.getChildNodes ();
int length = ls.getLength ();
for (int i=0;i