|
|
|
|
|
*/ |
|
/* |
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
* contributor license agreements. See the NOTICE file distributed with |
|
* this work for additional information regarding copyright ownership. |
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
* (the "License"); you may not use this file except in compliance with |
|
* the License. You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
package com.sun.org.apache.xerces.internal.impl.dtd; |
|
|
|
import com.sun.org.apache.xerces.internal.impl.Constants; |
|
import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; |
|
import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; |
|
import com.sun.org.apache.xerces.internal.util.SymbolTable; |
|
import com.sun.org.apache.xerces.internal.util.XMLChar; |
|
import com.sun.org.apache.xerces.internal.util.XMLSymbols; |
|
import com.sun.org.apache.xerces.internal.xni.Augmentations; |
|
import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; |
|
import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; |
|
import com.sun.org.apache.xerces.internal.xni.XMLLocator; |
|
import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; |
|
import com.sun.org.apache.xerces.internal.xni.XMLString; |
|
import com.sun.org.apache.xerces.internal.xni.XNIException; |
|
import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; |
|
import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; |
|
import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; |
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent; |
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; |
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; |
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelFilter; |
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource; |
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDFilter; |
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource; |
|
import java.util.ArrayList; |
|
import java.util.HashMap; |
|
import java.util.List; |
|
import java.util.Locale; |
|
import java.util.Map; |
|
import java.util.StringTokenizer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class XMLDTDProcessor |
|
implements XMLComponent, XMLDTDFilter, XMLDTDContentModelFilter { |
|
|
|
// |
|
// Constants |
|
// |
|
|
|
|
|
private static final int TOP_LEVEL_SCOPE = -1; |
|
|
|
// feature identifiers |
|
|
|
|
|
protected static final String VALIDATION = |
|
Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; |
|
|
|
|
|
protected static final String NOTIFY_CHAR_REFS = |
|
Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE; |
|
|
|
|
|
protected static final String WARN_ON_DUPLICATE_ATTDEF = |
|
Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE; |
|
|
|
|
|
protected static final String WARN_ON_UNDECLARED_ELEMDEF = |
|
Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE; |
|
|
|
protected static final String PARSER_SETTINGS = |
|
Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS; |
|
|
|
// property identifiers |
|
|
|
|
|
protected static final String SYMBOL_TABLE = |
|
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; |
|
|
|
|
|
protected static final String ERROR_REPORTER = |
|
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; |
|
|
|
|
|
protected static final String GRAMMAR_POOL = |
|
Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; |
|
|
|
|
|
protected static final String DTD_VALIDATOR = |
|
Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY; |
|
|
|
// recognized features and properties |
|
|
|
|
|
private static final String[] RECOGNIZED_FEATURES = { |
|
VALIDATION, |
|
WARN_ON_DUPLICATE_ATTDEF, |
|
WARN_ON_UNDECLARED_ELEMDEF, |
|
NOTIFY_CHAR_REFS, |
|
}; |
|
|
|
|
|
private static final Boolean[] FEATURE_DEFAULTS = { |
|
null, |
|
Boolean.FALSE, |
|
Boolean.FALSE, |
|
null, |
|
}; |
|
|
|
|
|
private static final String[] RECOGNIZED_PROPERTIES = { |
|
SYMBOL_TABLE, |
|
ERROR_REPORTER, |
|
GRAMMAR_POOL, |
|
DTD_VALIDATOR, |
|
}; |
|
|
|
|
|
private static final Object[] PROPERTY_DEFAULTS = { |
|
null, |
|
null, |
|
null, |
|
null, |
|
}; |
|
|
|
// debugging |
|
|
|
// |
|
// Data |
|
// |
|
|
|
// features |
|
|
|
|
|
protected boolean fValidation; |
|
|
|
|
|
protected boolean fDTDValidation; |
|
|
|
|
|
protected boolean fWarnDuplicateAttdef; |
|
|
|
|
|
protected boolean fWarnOnUndeclaredElemdef; |
|
|
|
// properties |
|
|
|
|
|
protected SymbolTable fSymbolTable; |
|
|
|
|
|
protected XMLErrorReporter fErrorReporter; |
|
|
|
|
|
protected DTDGrammarBucket fGrammarBucket; |
|
|
|
// the validator to which we look for our grammar bucket (the |
|
// validator needs to hold the bucket so that it can initialize |
|
|
|
protected XMLDTDValidator fValidator; |
|
|
|
|
|
protected XMLGrammarPool fGrammarPool; |
|
|
|
|
|
protected Locale fLocale; |
|
|
|
// handlers |
|
|
|
|
|
protected XMLDTDHandler fDTDHandler; |
|
|
|
|
|
protected XMLDTDSource fDTDSource; |
|
|
|
|
|
protected XMLDTDContentModelHandler fDTDContentModelHandler; |
|
|
|
|
|
protected XMLDTDContentModelSource fDTDContentModelSource; |
|
|
|
// grammars |
|
|
|
|
|
protected DTDGrammar fDTDGrammar; |
|
|
|
// state |
|
|
|
|
|
private boolean fPerformValidation; |
|
|
|
|
|
protected boolean fInDTDIgnore; |
|
|
|
// information regarding the current element |
|
|
|
// validation states |
|
|
|
|
|
private boolean fMixed; |
|
|
|
// temporary variables |
|
|
|
|
|
private final XMLEntityDecl fEntityDecl = new XMLEntityDecl(); |
|
|
|
|
|
private final Map<String, String> fNDataDeclNotations = new HashMap<>(); |
|
|
|
|
|
private String fDTDElementDeclName = null; |
|
|
|
|
|
private final List<String> fMixedElementTypes = new ArrayList<>(); |
|
|
|
|
|
private final List<String> fDTDElementDecls = new ArrayList<>(); |
|
|
|
// to check for duplicate ID or ANNOTATION attribute declare in |
|
// ATTLIST, and misc VCs |
|
|
|
|
|
private Map<String, String> fTableOfIDAttributeNames; |
|
|
|
|
|
private Map<String, String> fTableOfNOTATIONAttributeNames; |
|
|
|
|
|
private Map<String, String> fNotationEnumVals; |
|
|
|
// |
|
// Constructors |
|
// |
|
|
|
|
|
public XMLDTDProcessor() { |
|
|
|
// initialize data |
|
|
|
} // <init>() |
|
|
|
// |
|
// XMLComponent methods |
|
// |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void reset(XMLComponentManager componentManager) throws XMLConfigurationException { |
|
|
|
boolean parser_settings = componentManager.getFeature(PARSER_SETTINGS, true); |
|
|
|
if (!parser_settings) { |
|
|
|
reset(); |
|
return; |
|
} |
|
|
|
|
|
fValidation = componentManager.getFeature(VALIDATION, false); |
|
|
|
fDTDValidation = |
|
!(componentManager |
|
.getFeature( |
|
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE, false)); |
|
|
|
// Xerces features |
|
|
|
fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF, false); |
|
fWarnOnUndeclaredElemdef = componentManager.getFeature(WARN_ON_UNDECLARED_ELEMDEF, false); |
|
|
|
|
|
fErrorReporter = |
|
(XMLErrorReporter) componentManager.getProperty( |
|
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY); |
|
fSymbolTable = |
|
(SymbolTable) componentManager.getProperty( |
|
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY); |
|
|
|
fGrammarPool = (XMLGrammarPool) componentManager.getProperty(GRAMMAR_POOL, null); |
|
|
|
try { |
|
fValidator = (XMLDTDValidator) componentManager.getProperty(DTD_VALIDATOR, null); |
|
} catch (ClassCastException e) { |
|
fValidator = null; |
|
} |
|
|
|
if (fValidator != null) { |
|
fGrammarBucket = fValidator.getGrammarBucket(); |
|
} else { |
|
fGrammarBucket = null; |
|
} |
|
reset(); |
|
|
|
} // reset(XMLComponentManager) |
|
|
|
protected void reset() { |
|
|
|
fDTDGrammar = null; |
|
|
|
fInDTDIgnore = false; |
|
|
|
fNDataDeclNotations.clear(); |
|
|
|
|
|
if (fValidation) { |
|
|
|
if (fNotationEnumVals == null) { |
|
fNotationEnumVals = new HashMap<>(); |
|
} |
|
fNotationEnumVals.clear(); |
|
|
|
fTableOfIDAttributeNames = new HashMap<>(); |
|
fTableOfNOTATIONAttributeNames = new HashMap<>(); |
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public String[] getRecognizedFeatures() { |
|
return RECOGNIZED_FEATURES.clone(); |
|
} // getRecognizedFeatures():String[] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setFeature(String featureId, boolean state) |
|
throws XMLConfigurationException { |
|
} // setFeature(String,boolean) |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String[] getRecognizedProperties() { |
|
return RECOGNIZED_PROPERTIES.clone(); |
|
} // getRecognizedProperties():String[] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setProperty(String propertyId, Object value) |
|
throws XMLConfigurationException { |
|
} // setProperty(String,Object) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Boolean getFeatureDefault(String featureId) { |
|
for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) { |
|
if (RECOGNIZED_FEATURES[i].equals(featureId)) { |
|
return FEATURE_DEFAULTS[i]; |
|
} |
|
} |
|
return null; |
|
} // getFeatureDefault(String):Boolean |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Object getPropertyDefault(String propertyId) { |
|
for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) { |
|
if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) { |
|
return PROPERTY_DEFAULTS[i]; |
|
} |
|
} |
|
return null; |
|
} // getPropertyDefault(String):Object |
|
|
|
// |
|
// XMLDTDSource methods |
|
// |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setDTDHandler(XMLDTDHandler dtdHandler) { |
|
fDTDHandler = dtdHandler; |
|
} // setDTDHandler(XMLDTDHandler) |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public XMLDTDHandler getDTDHandler() { |
|
return fDTDHandler; |
|
} // getDTDHandler(): XMLDTDHandler |
|
|
|
// |
|
// XMLDTDContentModelSource methods |
|
// |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setDTDContentModelHandler(XMLDTDContentModelHandler dtdContentModelHandler) { |
|
fDTDContentModelHandler = dtdContentModelHandler; |
|
} // setDTDContentModelHandler(XMLDTDContentModelHandler) |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public XMLDTDContentModelHandler getDTDContentModelHandler() { |
|
return fDTDContentModelHandler; |
|
} // getDTDContentModelHandler(): XMLDTDContentModelHandler |
|
|
|
// |
|
// XMLDTDContentModelHandler and XMLDTDHandler methods |
|
// |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void startExternalSubset(XMLResourceIdentifier identifier, |
|
Augmentations augs) throws XNIException { |
|
if(fDTDGrammar != null) |
|
fDTDGrammar.startExternalSubset(identifier, augs); |
|
if(fDTDHandler != null){ |
|
fDTDHandler.startExternalSubset(identifier, augs); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void endExternalSubset(Augmentations augs) throws XNIException { |
|
if(fDTDGrammar != null) |
|
fDTDGrammar.endExternalSubset(augs); |
|
if(fDTDHandler != null){ |
|
fDTDHandler.endExternalSubset(augs); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected static void checkStandaloneEntityRef(String name, DTDGrammar grammar, |
|
XMLEntityDecl tempEntityDecl, XMLErrorReporter errorReporter) throws XNIException { |
|
|
|
int entIndex = grammar.getEntityDeclIndex(name); |
|
if (entIndex > -1) { |
|
grammar.getEntityDecl(entIndex, tempEntityDecl); |
|
if (tempEntityDecl.inExternal) { |
|
errorReporter.reportError( XMLMessageFormatter.XML_DOMAIN, |
|
"MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE", |
|
new Object[]{name}, XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void comment(XMLString text, Augmentations augs) throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.comment(text, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.comment(text, augs); |
|
} |
|
|
|
} // comment(XMLString) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void processingInstruction(String target, XMLString data, Augmentations augs) |
|
throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.processingInstruction(target, data, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.processingInstruction(target, data, augs); |
|
} |
|
} // processingInstruction(String,XMLString) |
|
|
|
// |
|
// XMLDTDHandler methods |
|
// |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException { |
|
|
|
|
|
|
|
fNDataDeclNotations.clear(); |
|
fDTDElementDecls.clear(); |
|
|
|
// the grammar bucket's DTDGrammar will now be the |
|
// one we want, whether we're constructing it or not. |
|
// if we're not constructing it, then we should not have a reference |
|
|
|
if( !fGrammarBucket.getActiveGrammar().isImmutable()) { |
|
fDTDGrammar = fGrammarBucket.getActiveGrammar(); |
|
} |
|
|
|
|
|
if(fDTDGrammar != null ) |
|
fDTDGrammar.startDTD(locator, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.startDTD(locator, augs); |
|
} |
|
|
|
} // startDTD(XMLLocator) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void ignoredCharacters(XMLString text, Augmentations augs) throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null ) |
|
fDTDGrammar.ignoredCharacters(text, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.ignoredCharacters(text, augs); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void textDecl(String version, String encoding, Augmentations augs) throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null ) |
|
fDTDGrammar.textDecl(version, encoding, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.textDecl(version, encoding, augs); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void startParameterEntity(String name, |
|
XMLResourceIdentifier identifier, |
|
String encoding, |
|
Augmentations augs) throws XNIException { |
|
|
|
if (fPerformValidation && fDTDGrammar != null && |
|
fGrammarBucket.getStandalone()) { |
|
checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter); |
|
} |
|
|
|
if(fDTDGrammar != null ) |
|
fDTDGrammar.startParameterEntity(name, identifier, encoding, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.startParameterEntity(name, identifier, encoding, augs); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void endParameterEntity(String name, Augmentations augs) throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null ) |
|
fDTDGrammar.endParameterEntity(name, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.endParameterEntity(name, augs); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void elementDecl(String name, String contentModel, Augmentations augs) |
|
throws XNIException { |
|
|
|
|
|
if (fValidation) { |
|
if (fDTDElementDecls.contains(name)) { |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"MSG_ELEMENT_ALREADY_DECLARED", |
|
new Object[]{ name}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
else { |
|
fDTDElementDecls.add(name); |
|
} |
|
} |
|
|
|
|
|
if(fDTDGrammar != null ) |
|
fDTDGrammar.elementDecl(name, contentModel, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.elementDecl(name, contentModel, augs); |
|
} |
|
|
|
} // elementDecl(String,String) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void startAttlist(String elementName, Augmentations augs) |
|
throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null ) |
|
fDTDGrammar.startAttlist(elementName, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.startAttlist(elementName, augs); |
|
} |
|
|
|
} // startAttlist(String) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void attributeDecl(String elementName, String attributeName, |
|
String type, String[] enumeration, |
|
String defaultType, XMLString defaultValue, |
|
XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException { |
|
|
|
if (type != XMLSymbols.fCDATASymbol && defaultValue != null) { |
|
normalizeDefaultAttrValue(defaultValue); |
|
} |
|
|
|
if (fValidation) { |
|
|
|
boolean duplicateAttributeDef = false ; |
|
|
|
|
|
DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar:fGrammarBucket.getActiveGrammar()); |
|
int elementIndex = grammar.getElementDeclIndex( elementName); |
|
if (grammar.getAttributeDeclIndex(elementIndex, attributeName) != -1) { |
|
|
|
duplicateAttributeDef = true ; |
|
|
|
|
|
if(fWarnDuplicateAttdef){ |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"MSG_DUPLICATE_ATTRIBUTE_DEFINITION", |
|
new Object[]{ elementName, attributeName }, |
|
XMLErrorReporter.SEVERITY_WARNING ); |
|
} |
|
} |
|
|
|
|
|
// |
|
// a) VC: One ID per Element Type, If duplicate ID attribute |
|
// b) VC: ID attribute Default. if there is a declareared attribute |
|
|
|
if (type == XMLSymbols.fIDSymbol) { |
|
if (defaultValue != null && defaultValue.length != 0) { |
|
if (defaultType == null || |
|
!(defaultType == XMLSymbols.fIMPLIEDSymbol || |
|
defaultType == XMLSymbols.fREQUIREDSymbol)) { |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"IDDefaultTypeInvalid", |
|
new Object[]{ attributeName}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
} |
|
|
|
if (!fTableOfIDAttributeNames.containsKey(elementName)) { |
|
fTableOfIDAttributeNames.put(elementName, attributeName); |
|
} |
|
else { |
|
//we should not report an error, when there is duplicate attribute definition for given element type |
|
//according to XML 1.0 spec, When more than one definition is provided for the same attribute of a given |
|
//element type, the first declaration is binding and later declaration are *ignored*. So processor should |
|
//ignore the second declarations, however an application would be warned of the duplicate attribute defintion |
|
// if http://apache.org/xml/features/validation/warn-on-duplicate-attdef feature is set to true, |
|
// one typical case where this could be a problem, when any XML file |
|
// provide the ID type information through internal subset so that it is available to the parser which read |
|
//only internal subset. Now that attribute declaration(ID Type) can again be part of external parsed entity |
|
//referenced. At that time if parser doesn't make this distinction it will throw an error for VC One ID per |
|
//Element Type, which (second defintion) actually should be ignored. Application behavior may differ on the |
|
//basis of error or warning thrown. - nb. |
|
|
|
if(!duplicateAttributeDef){ |
|
String previousIDAttributeName = fTableOfIDAttributeNames.get( elementName ); |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"MSG_MORE_THAN_ONE_ID_ATTRIBUTE", |
|
new Object[]{ elementName, previousIDAttributeName, attributeName}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
} |
|
} |
|
|
|
// |
|
// VC: One Notation Per Element Type, should check if there is a |
|
// duplicate NOTATION attribute |
|
|
|
if (type == XMLSymbols.fNOTATIONSymbol) { |
|
// VC: Notation Attributes: all notation names in the |
|
|
|
for (int i=0; i<enumeration.length; i++) { |
|
fNotationEnumVals.put(enumeration[i], attributeName); |
|
} |
|
|
|
if (fTableOfNOTATIONAttributeNames.containsKey( elementName ) == false) { |
|
fTableOfNOTATIONAttributeNames.put( elementName, attributeName); |
|
} |
|
else { |
|
//we should not report an error, when there is duplicate attribute definition for given element type |
|
//according to XML 1.0 spec, When more than one definition is provided for the same attribute of a given |
|
//element type, the first declaration is binding and later declaration are *ignored*. So processor should |
|
//ignore the second declarations, however an application would be warned of the duplicate attribute definition |
|
// if http://apache.org/xml/features/validation/warn-on-duplicate-attdef feature is set to true, |
|
// Application behavior may differ on the basis of error or warning thrown. - nb. |
|
|
|
if(!duplicateAttributeDef){ |
|
|
|
String previousNOTATIONAttributeName = fTableOfNOTATIONAttributeNames.get( elementName ); |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE", |
|
new Object[]{ elementName, previousNOTATIONAttributeName, attributeName}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
} |
|
} |
|
|
|
// VC: No Duplicate Tokens |
|
|
|
if (type == XMLSymbols.fENUMERATIONSymbol || type == XMLSymbols.fNOTATIONSymbol) { |
|
outer: |
|
for (int i = 0; i < enumeration.length; ++i) { |
|
for (int j = i + 1; j < enumeration.length; ++j) { |
|
if (enumeration[i].equals(enumeration[j])) { |
|
// Only report the first uniqueness violation. There could be others, |
|
// but additional overhead would be incurred tracking unique tokens |
|
|
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
type == XMLSymbols.fENUMERATIONSymbol |
|
? "MSG_DISTINCT_TOKENS_IN_ENUMERATION" |
|
: "MSG_DISTINCT_NOTATION_IN_ENUMERATION", |
|
new Object[]{ elementName, enumeration[i], attributeName }, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
break outer; |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
boolean ok = true; |
|
if (defaultValue != null && |
|
(defaultType == null || |
|
(defaultType != null && defaultType == XMLSymbols.fFIXEDSymbol))) { |
|
|
|
String value = defaultValue.toString(); |
|
if (type == XMLSymbols.fNMTOKENSSymbol || |
|
type == XMLSymbols.fENTITIESSymbol || |
|
type == XMLSymbols.fIDREFSSymbol) { |
|
|
|
StringTokenizer tokenizer = new StringTokenizer(value," "); |
|
if (tokenizer.hasMoreTokens()) { |
|
while (true) { |
|
String nmtoken = tokenizer.nextToken(); |
|
if (type == XMLSymbols.fNMTOKENSSymbol) { |
|
if (!isValidNmtoken(nmtoken)) { |
|
ok = false; |
|
break; |
|
} |
|
} |
|
else if (type == XMLSymbols.fENTITIESSymbol || |
|
type == XMLSymbols.fIDREFSSymbol) { |
|
if (!isValidName(nmtoken)) { |
|
ok = false; |
|
break; |
|
} |
|
} |
|
if (!tokenizer.hasMoreTokens()) { |
|
break; |
|
} |
|
} |
|
} |
|
|
|
} |
|
else { |
|
if (type == XMLSymbols.fENTITYSymbol || |
|
type == XMLSymbols.fIDSymbol || |
|
type == XMLSymbols.fIDREFSymbol || |
|
type == XMLSymbols.fNOTATIONSymbol) { |
|
|
|
if (!isValidName(value)) { |
|
ok = false; |
|
} |
|
|
|
} |
|
else if (type == XMLSymbols.fNMTOKENSymbol || |
|
type == XMLSymbols.fENUMERATIONSymbol) { |
|
|
|
if (!isValidNmtoken(value)) { |
|
ok = false; |
|
} |
|
} |
|
|
|
if (type == XMLSymbols.fNOTATIONSymbol || |
|
type == XMLSymbols.fENUMERATIONSymbol) { |
|
ok = false; |
|
for (int i=0; i<enumeration.length; i++) { |
|
if (defaultValue.equals(enumeration[i])) { |
|
ok = true; |
|
} |
|
} |
|
} |
|
|
|
} |
|
if (!ok) { |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"MSG_ATT_DEFAULT_INVALID", |
|
new Object[]{attributeName, value}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
} |
|
} |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.attributeDecl(elementName, attributeName, |
|
type, enumeration, |
|
defaultType, defaultValue, nonNormalizedDefaultValue, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.attributeDecl(elementName, attributeName, |
|
type, enumeration, |
|
defaultType, defaultValue, nonNormalizedDefaultValue, augs); |
|
} |
|
|
|
} // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void endAttlist(Augmentations augs) throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.endAttlist(augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.endAttlist(augs); |
|
} |
|
|
|
} // endAttlist() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void internalEntityDecl(String name, XMLString text, |
|
XMLString nonNormalizedText, |
|
Augmentations augs) throws XNIException { |
|
|
|
DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar()); |
|
int index = grammar.getEntityDeclIndex(name) ; |
|
|
|
//If the same entity is declared more than once, the first declaration |
|
//encountered is binding, SAX requires only effective(first) declaration |
|
//to be reported to the application |
|
|
|
//REVISIT: Does it make sense to pass duplicate Entity information across |
|
//the pipeline -- nb? |
|
|
|
|
|
if(index == -1){ |
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.internalEntityDecl(name, text, nonNormalizedText, augs); |
|
|
|
if (fDTDHandler != null) { |
|
fDTDHandler.internalEntityDecl(name, text, nonNormalizedText, augs); |
|
} |
|
} |
|
|
|
} // internalEntityDecl(String,XMLString,XMLString) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void externalEntityDecl(String name, XMLResourceIdentifier identifier, |
|
Augmentations augs) throws XNIException { |
|
|
|
DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar()); |
|
int index = grammar.getEntityDeclIndex(name) ; |
|
|
|
//If the same entity is declared more than once, the first declaration |
|
//encountered is binding, SAX requires only effective(first) declaration |
|
//to be reported to the application |
|
|
|
//REVISIT: Does it make sense to pass duplicate entity information across |
|
//the pipeline -- nb? |
|
|
|
|
|
if(index == -1){ |
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.externalEntityDecl(name, identifier, augs); |
|
|
|
if (fDTDHandler != null) { |
|
fDTDHandler.externalEntityDecl(name, identifier, augs); |
|
} |
|
} |
|
|
|
} // externalEntityDecl(String,XMLResourceIdentifier, Augmentations) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, |
|
String notation, |
|
Augmentations augs) throws XNIException { |
|
|
|
|
|
if (fValidation) { |
|
fNDataDeclNotations.put(name, notation); |
|
} |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.unparsedEntityDecl(name, identifier, notation, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.unparsedEntityDecl(name, identifier, notation, augs); |
|
} |
|
|
|
} // unparsedEntityDecl(String,XMLResourceIdentifier,String,Augmentations) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void notationDecl(String name, XMLResourceIdentifier identifier, |
|
Augmentations augs) throws XNIException { |
|
|
|
|
|
if (fValidation) { |
|
DTDGrammar grammar = (fDTDGrammar != null ? fDTDGrammar : fGrammarBucket.getActiveGrammar()); |
|
if (grammar.getNotationDeclIndex(name) != -1) { |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"UniqueNotationName", |
|
new Object[]{name}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
} |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.notationDecl(name, identifier, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.notationDecl(name, identifier, augs); |
|
} |
|
|
|
} // notationDecl(String,XMLResourceIdentifier, Augmentations) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void startConditional(short type, Augmentations augs) throws XNIException { |
|
|
|
|
|
fInDTDIgnore = type == XMLDTDHandler.CONDITIONAL_IGNORE; |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.startConditional(type, augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.startConditional(type, augs); |
|
} |
|
|
|
} // startConditional(short) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void endConditional(Augmentations augs) throws XNIException { |
|
|
|
|
|
fInDTDIgnore = false; |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.endConditional(augs); |
|
if (fDTDHandler != null) { |
|
fDTDHandler.endConditional(augs); |
|
} |
|
|
|
} // endConditional() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void endDTD(Augmentations augs) throws XNIException { |
|
|
|
|
|
|
|
if(fDTDGrammar != null) { |
|
fDTDGrammar.endDTD(augs); |
|
if(fGrammarPool != null) |
|
fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_DTD, new Grammar[] {fDTDGrammar}); |
|
} |
|
if (fValidation) { |
|
DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar()); |
|
|
|
|
|
for (Map.Entry<String, String> entry : fNDataDeclNotations.entrySet()) { |
|
String notation = entry.getValue(); |
|
if (grammar.getNotationDeclIndex(notation) == -1) { |
|
String entity = entry.getKey(); |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"MSG_NOTATION_NOT_DECLARED_FOR_UNPARSED_ENTITYDECL", |
|
new Object[]{entity, notation}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
} |
|
|
|
for (Map.Entry<String, String> entry : fNotationEnumVals.entrySet()) { |
|
String notation = entry.getKey(); |
|
if (grammar.getNotationDeclIndex(notation) == -1) { |
|
String attributeName = entry.getValue(); |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE", |
|
new Object[]{attributeName, notation}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
} |
|
|
|
// VC: No Notation on Empty Element |
|
|
|
for (Map.Entry<String, String> entry : fTableOfNOTATIONAttributeNames.entrySet()) { |
|
String elementName = entry.getKey(); |
|
int elementIndex = grammar.getElementDeclIndex(elementName); |
|
if (grammar.getContentSpecType(elementIndex) == XMLElementDecl.TYPE_EMPTY) { |
|
String attributeName = entry.getValue(); |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"NoNotationOnEmptyElement", |
|
new Object[]{elementName, attributeName}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
} |
|
|
|
|
|
fTableOfIDAttributeNames = null; |
|
fTableOfNOTATIONAttributeNames = null; |
|
|
|
|
|
if (fWarnOnUndeclaredElemdef) { |
|
checkDeclaredElements(grammar); |
|
} |
|
} |
|
|
|
|
|
if (fDTDHandler != null) { |
|
fDTDHandler.endDTD(augs); |
|
} |
|
|
|
} // endDTD() |
|
|
|
|
|
public void setDTDSource(XMLDTDSource source ) { |
|
fDTDSource = source; |
|
} // setDTDSource(XMLDTDSource) |
|
|
|
|
|
public XMLDTDSource getDTDSource() { |
|
return fDTDSource; |
|
} // getDTDSource(): XMLDTDSource |
|
|
|
// |
|
// XMLDTDContentModelHandler methods |
|
// |
|
|
|
|
|
public void setDTDContentModelSource(XMLDTDContentModelSource source ) { |
|
fDTDContentModelSource = source; |
|
} // setDTDContentModelSource(XMLDTDContentModelSource) |
|
|
|
|
|
public XMLDTDContentModelSource getDTDContentModelSource() { |
|
return fDTDContentModelSource; |
|
} // getDTDContentModelSource(): XMLDTDContentModelSource |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void startContentModel(String elementName, Augmentations augs) |
|
throws XNIException { |
|
|
|
if (fValidation) { |
|
fDTDElementDeclName = elementName; |
|
fMixedElementTypes.clear(); |
|
} |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.startContentModel(elementName, augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.startContentModel(elementName, augs); |
|
} |
|
|
|
} // startContentModel(String) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void any(Augmentations augs) throws XNIException { |
|
if(fDTDGrammar != null) |
|
fDTDGrammar.any(augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.any(augs); |
|
} |
|
} // any() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void empty(Augmentations augs) throws XNIException { |
|
if(fDTDGrammar != null) |
|
fDTDGrammar.empty(augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.empty(augs); |
|
} |
|
} // empty() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void startGroup(Augmentations augs) throws XNIException { |
|
|
|
fMixed = false; |
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.startGroup(augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.startGroup(augs); |
|
} |
|
|
|
} // startGroup() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void pcdata(Augmentations augs) { |
|
fMixed = true; |
|
if(fDTDGrammar != null) |
|
fDTDGrammar.pcdata(augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.pcdata(augs); |
|
} |
|
} // pcdata() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void element(String elementName, Augmentations augs) throws XNIException { |
|
|
|
|
|
if (fMixed && fValidation) { |
|
if (fMixedElementTypes.contains(elementName)) { |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"DuplicateTypeInMixedContent", |
|
new Object[]{fDTDElementDeclName, elementName}, |
|
XMLErrorReporter.SEVERITY_ERROR); |
|
} |
|
else { |
|
fMixedElementTypes.add(elementName); |
|
} |
|
} |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.element(elementName, augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.element(elementName, augs); |
|
} |
|
|
|
} // childrenElement(String) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void separator(short separator, Augmentations augs) |
|
throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.separator(separator, augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.separator(separator, augs); |
|
} |
|
|
|
} // separator(short) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void occurrence(short occurrence, Augmentations augs) |
|
throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.occurrence(occurrence, augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.occurrence(occurrence, augs); |
|
} |
|
|
|
} // occurrence(short) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void endGroup(Augmentations augs) throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.endGroup(augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.endGroup(augs); |
|
} |
|
|
|
} // endGroup() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void endContentModel(Augmentations augs) throws XNIException { |
|
|
|
|
|
if(fDTDGrammar != null) |
|
fDTDGrammar.endContentModel(augs); |
|
if (fDTDContentModelHandler != null) { |
|
fDTDContentModelHandler.endContentModel(augs); |
|
} |
|
|
|
} // endContentModel() |
|
|
|
// |
|
// Private methods |
|
// |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private boolean normalizeDefaultAttrValue(XMLString value) { |
|
|
|
boolean skipSpace = true; |
|
int current = value.offset; |
|
int end = value.offset + value.length; |
|
for (int i = value.offset; i < end; i++) { |
|
if (value.ch[i] == ' ') { |
|
if (!skipSpace) { |
|
|
|
value.ch[current++] = ' '; |
|
skipSpace = true; |
|
} |
|
else { |
|
// just skip it. |
|
} |
|
} |
|
else { |
|
|
|
if (current != i) { |
|
value.ch[current] = value.ch[i]; |
|
} |
|
current++; |
|
skipSpace = false; |
|
} |
|
} |
|
if (current != end) { |
|
if (skipSpace) { |
|
|
|
current--; |
|
} |
|
|
|
value.length = current - value.offset; |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
protected boolean isValidNmtoken(String nmtoken) { |
|
return XMLChar.isValidNmtoken(nmtoken); |
|
} // isValidNmtoken(String): boolean |
|
|
|
protected boolean isValidName(String name) { |
|
return XMLChar.isValidName(name); |
|
} // isValidName(String): boolean |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private void checkDeclaredElements(DTDGrammar grammar) { |
|
int elementIndex = grammar.getFirstElementDeclIndex(); |
|
XMLContentSpec contentSpec = new XMLContentSpec(); |
|
while (elementIndex >= 0) { |
|
int type = grammar.getContentSpecType(elementIndex); |
|
if (type == XMLElementDecl.TYPE_CHILDREN || type == XMLElementDecl.TYPE_MIXED) { |
|
checkDeclaredElements(grammar, |
|
elementIndex, |
|
grammar.getContentSpecIndex(elementIndex), |
|
contentSpec); |
|
} |
|
elementIndex = grammar.getNextElementDeclIndex(elementIndex); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private void checkDeclaredElements(DTDGrammar grammar, int elementIndex, |
|
int contentSpecIndex, XMLContentSpec contentSpec) { |
|
grammar.getContentSpec(contentSpecIndex, contentSpec); |
|
if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) { |
|
String value = (String) contentSpec.value; |
|
if (value != null && grammar.getElementDeclIndex(value) == -1) { |
|
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
"UndeclaredElementInContentSpec", |
|
new Object[]{grammar.getElementDeclName(elementIndex).rawname, value}, |
|
XMLErrorReporter.SEVERITY_WARNING); |
|
} |
|
} |
|
// It's not a leaf, so we have to recurse its left and maybe right |
|
|
|
else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE) |
|
|| (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) { |
|
final int leftNode = ((int[])contentSpec.value)[0]; |
|
final int rightNode = ((int[])contentSpec.otherValue)[0]; |
|
|
|
checkDeclaredElements(grammar, elementIndex, leftNode, contentSpec); |
|
checkDeclaredElements(grammar, elementIndex, rightNode, contentSpec); |
|
} |
|
else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE |
|
|| contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE |
|
|| contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) { |
|
final int leftNode = ((int[])contentSpec.value)[0]; |
|
checkDeclaredElements(grammar, elementIndex, leftNode, contentSpec); |
|
} |
|
} |
|
|
|
} // class XMLDTDProcessor |