mrglavas 2003/10/10 11:25:40
Modified: java/src/org/apache/xerces/util XMLAttributesImpl.java
java/src/org/apache/xerces/impl/dtd XMLNSDTDValidator.java
XML11NSDTDValidator.java
java/src/org/apache/xerces/impl
XML11NSDocumentScannerImpl.java
XMLNSDocumentScannerImpl.java
XMLNamespaceBinder.java
Log:
Improved processing of attribute lists both small and large
in many ways. Take advantage of the SymbolTable and
always use reference comparison when checking names.
Revision Changes Path
1.21 +438 -55
xml-xerces/java/src/org/apache/xerces/util/XMLAttributesImpl.java
Index: XMLAttributesImpl.java
===================================================================
RCS file:
/home/cvs/xml-xerces/java/src/org/apache/xerces/util/XMLAttributesImpl.java,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- XMLAttributesImpl.java 8 May 2003 20:12:00 -0000 1.20
+++ XMLAttributesImpl.java 10 Oct 2003 18:25:40 -0000 1.21
@@ -76,6 +76,7 @@
*
* @author Andy Clark, IBM
* @author Elena Litani, IBM
+ * @author Michael Glavassevich, IBM
*
* @version $Id$
*/
@@ -83,6 +84,19 @@
implements XMLAttributes {
//
+ // Constants
+ //
+
+ /** Default table size. */
+ protected static final int TABLE_SIZE = 101;
+
+ /**
+ * Threshold at which an instance is treated
+ * as a large attribute list.
+ */
+ protected static final int SIZE_LIMIT = 20;
+
+ //
// Data
//
@@ -93,18 +107,42 @@
// data
+ /**
+ * Usage count for the attribute table view.
+ * Incremented each time all attributes are removed
+ * when the attribute table view is in use.
+ */
+ protected int fLargeCount = 1;
+
/** Attribute count. */
protected int fLength;
/** Attribute information. */
protected Attribute[] fAttributes = new Attribute[4];
-
- /** Augmentations information for each attribute
- number of augmentations is equal to the number of attributes
- */
- // XMLAttributes has no knowledge if any augmentations
- // we attached to Augmentations.
- protected Augmentations[] fAugmentations = new AugmentationsImpl[4];
+
+ /**
+ * Hashtable of attribute information.
+ * Provides an alternate view of the attribute specification.
+ */
+ protected Attribute[] fAttributeTableView;
+
+ /**
+ * Tracks whether each chain in the hash table is stale
+ * with respect to the current state of this object.
+ * A chain is stale if its state is not the same as the number
+ * of times the attribute table view has been used.
+ */
+ protected int[] fAttributeTableViewChainState;
+
+ /**
+ * Actual number of buckets in the table view.
+ */
+ protected int fTableViewBuckets;
+
+ /**
+ * Indicates whether the table view contains consistent data.
+ */
+ protected boolean fIsTableViewConsistent;
//
// Constructors
@@ -112,9 +150,16 @@
/** Default constructor. */
public XMLAttributesImpl() {
+ this(TABLE_SIZE);
+ }
+
+ /**
+ * @param tableSize initial size of table view
+ */
+ public XMLAttributesImpl(int tableSize) {
+ fTableViewBuckets = tableSize;
for (int i = 0; i < fAttributes.length; i++) {
fAttributes[i] = new Attribute();
- fAugmentations[i] = new AugmentationsImpl();
}
} // <init>()
@@ -150,8 +195,8 @@
* exists, the old values for the attribute are replaced by the new
* values.
*
- * @param attrName The attribute name.
- * @param attrType The attribute type. The type name is determined by
+ * @param name The attribute name.
+ * @param type The attribute type. The type name is determined by
* the type specified for this attribute in the DTD.
* For example: "CDATA", "ID", "NMTOKEN", etc. However,
* attributes of type enumeration will have the type
@@ -159,7 +204,7 @@
* the enumeration values prefixed by an open
* parenthesis and suffixed by a close parenthesis.
* For example: "(true|false)".
- * @param attrValue The attribute value.
+ * @param value The attribute value.
*
* @return Returns the attribute index.
*
@@ -168,29 +213,95 @@
*/
public int addAttribute(QName name, String type, String value) {
- // find attribute; create, if necessary
- int index = name.uri != null && !name.uri.equals("")
- ? getIndex(name.uri, name.localpart)
- : getIndex(name.rawname);
- if (index == -1) {
- index = fLength;
- if (fLength++ == fAttributes.length) {
- Attribute[] attributes = new Attribute[fAttributes.length + 4];
- Augmentations[] augs = new AugmentationsImpl[fAttributes.length +4];
- System.arraycopy(fAttributes, 0, attributes, 0, fAttributes.length);
- System.arraycopy(fAugmentations, 0, augs, 0, fAttributes.length);
- for (int i = fAttributes.length; i < attributes.length; i++) {
- attributes[i] = new Attribute();
- augs[i] = new AugmentationsImpl();
+ int index;
+ if (fLength < SIZE_LIMIT) {
+ index = name.uri != null && !name.uri.equals("")
+ ? getIndexFast(name.uri, name.localpart)
+ : getIndexFast(name.rawname);
+
+ if (index == -1) {
+ index = fLength;
+ if (fLength++ == fAttributes.length) {
+ Attribute[] attributes = new Attribute[fAttributes.length + 4];
+ System.arraycopy(fAttributes, 0, attributes, 0,
fAttributes.length);
+ for (int i = fAttributes.length; i < attributes.length; i++) {
+ attributes[i] = new Attribute();
+ }
+ fAttributes = attributes;
}
- fAttributes = attributes;
- fAugmentations = augs;
}
}
+ else if (name.uri == null ||
+ name.uri.length() == 0 ||
+ (index = getIndexFast(name.uri, name.localpart)) == -1) {
+
+ /**
+ * If attributes were removed from the list after the table
+ * becomes in use this isn't reflected in the table view. It's
+ * assumed that once a user starts removing attributes they're
+ * not likely to add more. We only make the view consistent if
+ * the user of this class adds attributes, removes them, and
+ * then adds more.
+ */
+ if (!fIsTableViewConsistent || fLength == SIZE_LIMIT) {
+ prepareAndPopulateTableView();
+ fIsTableViewConsistent = true;
+ }
- // clear augmentations
- fAugmentations[index].removeAllItems();
-
+ int bucket = getTableViewBucket(name.rawname);
+
+ // The chain is stale.
+ // This must be a unique attribute.
+ if (fAttributeTableViewChainState[bucket] != fLargeCount) {
+ index = fLength;
+ if (fLength++ == fAttributes.length) {
+ Attribute[] attributes = new Attribute[fAttributes.length << 1];
+ System.arraycopy(fAttributes, 0, attributes, 0,
fAttributes.length);
+ for (int i = fAttributes.length; i < attributes.length; i++) {
+ attributes[i] = new Attribute();
+ }
+ fAttributes = attributes;
+ }
+
+ // Update table view.
+ fAttributeTableViewChainState[bucket] = fLargeCount;
+ fAttributes[index].next = null;
+ fAttributeTableView[bucket] = fAttributes[index];
+ }
+ // This chain is active.
+ // We need to check if any of the attributes has the same rawname.
+ else {
+ // Search the table.
+ Attribute found = fAttributeTableView[bucket];
+ while (found != null) {
+ if (found.name.rawname == name.rawname) {
+ break;
+ }
+ found = found.next;
+ }
+ // This attribute is unique.
+ if (found == null) {
+ index = fLength;
+ if (fLength++ == fAttributes.length) {
+ Attribute[] attributes = new Attribute[fAttributes.length
<< 1];
+ System.arraycopy(fAttributes, 0, attributes, 0,
fAttributes.length);
+ for (int i = fAttributes.length; i < attributes.length;
i++) {
+ attributes[i] = new Attribute();
+ }
+ fAttributes = attributes;
+ }
+
+ // Update table view
+ fAttributes[index].next = fAttributeTableView[bucket];
+ fAttributeTableView[bucket] = fAttributes[index];
+ }
+ // Duplicate. We still need to find the index.
+ else {
+ index = getIndexFast(name.rawname);
+ }
+ }
+ }
+
// set values
Attribute attribute = fAttributes[index];
attribute.name.setValues(name);
@@ -198,8 +309,10 @@
attribute.value = value;
attribute.nonNormalizedValue = value;
attribute.specified = false;
+
+ // clear augmentations
+ attribute.augs.removeAllItems();
- // return
return index;
} // addAttribute(QName,String,XMLString)
@@ -221,20 +334,14 @@
* @param attrIndex The attribute index.
*/
public void removeAttributeAt(int attrIndex) {
+ fIsTableViewConsistent = false;
if (attrIndex < fLength - 1) {
Attribute removedAttr = fAttributes[attrIndex];
- Augmentations removedAug = fAugmentations[attrIndex];
System.arraycopy(fAttributes, attrIndex + 1,
- fAttributes, attrIndex, fLength - attrIndex - 1);
-
- System.arraycopy(fAugmentations, attrIndex + 1,
- fAugmentations, attrIndex, fLength - attrIndex - 1);
-
+ fAttributes, attrIndex, fLength - attrIndex - 1);
// Make the discarded Attribute object available for re-use
// by tucking it after the Attributes that are still in use
fAttributes[fLength-1] = removedAttr;
-
- fAugmentations[fLength-1] = removedAug;
}
fLength--;
} // removeAttributeAt(int)
@@ -379,11 +486,7 @@
if (index < 0 || index >= fLength) {
return null;
}
- String type = fAttributes[index].type;
- if(type.indexOf('(') == 0 && type.lastIndexOf(')') == type.length()-1) {
- return "NMTOKEN";
- }
- return type;
+ return getReportableType(fAttributes[index].type);
} // getType(int):String
/**
@@ -399,7 +502,7 @@
*/
public String getType(String qname) {
int index = getIndex(qname);
- return index != -1 ? getType(index): null;
+ return index != -1 ? getReportableType(fAttributes[index].type) : null;
} // getType(String):String
/**
@@ -564,7 +667,7 @@
return null;
}
int index = getIndex(uri, localName);
- return index != -1 ? getType(index) : null;
+ return index != -1 ? getReportableType(fAttributes[index].type) : null;
} // getType(String,String):String
/**
@@ -622,8 +725,7 @@
*/
public Augmentations getAugmentations (String uri, String localName) {
int index = getIndex(uri, localName);
-
- return index != -1 ? fAugmentations[index] : null;
+ return index != -1 ? fAttributes[index].augs : null;
}
/**
@@ -637,11 +739,9 @@
*/
public Augmentations getAugmentations(String qName){
int index = getIndex(qName);
- return index != -1 ? fAugmentations[index] : null;
+ return index != -1 ? fAttributes[index].augs : null;
}
-
-
/**
* Look up an augmentations by attributes index.
*
@@ -652,7 +752,7 @@
if (attributeIndex < 0 || attributeIndex >= fLength) {
return null;
}
- return fAugmentations[attributeIndex];
+ return fAttributes[attributeIndex].augs;
}
/**
@@ -662,7 +762,7 @@
* @param augs The augmentations.
*/
public void setAugmentations(int attrIndex, Augmentations augs) {
- fAugmentations[attrIndex] = augs;
+ fAttributes[attrIndex].augs = augs;
}
/**
@@ -687,7 +787,7 @@
}
public boolean getSchemaId(String qname) {
int index = getIndex(qname);
- return index != -1 ? fAttributes[index].schemaId : false;
+ return index != -1 ? fAttributes[index].schemaId : false;
} // getType(String):String
public boolean getSchemaId(String uri, String localName) {
if (!fNamespaces) {
@@ -696,6 +796,277 @@
int index = getIndex(uri, localName);
return index != -1 ? fAttributes[index].schemaId : false;
} // getType(String,String):String
+
+ /**
+ * Look up the index of an attribute by XML 1.0 qualified name.
+ * <p>
+ * <strong>Note:</strong>
+ * This method uses reference comparison, and thus should
+ * only be used internally. We cannot use this method in any
+ * code exposed to users as they may not pass in unique strings.
+ *
+ * @param qName The qualified (prefixed) name.
+ * @return The index of the attribute, or -1 if it does not
+ * appear in the list.
+ */
+ public int getIndexFast(String qName) {
+ for (int i = 0; i < fLength; ++i) {
+ Attribute attribute = fAttributes[i];
+ if (attribute.name.rawname == qName) {
+ return i;
+ }
+ }
+ return -1;
+ } // getIndexFast(String):int
+
+ /**
+ * Adds an attribute. The attribute's non-normalized value of the
+ * attribute will have the same value as the attribute value until
+ * set using the <code>setNonNormalizedValue</code> method. Also,
+ * the added attribute will be marked as specified in the XML instance
+ * document unless set otherwise using the <code>setSpecified</code>
+ * method.
+ * <p>
+ * This method differs from <code>addAttribute</code> in that it
+ * does not check if an attribute of the same name already exists
+ * in the list before adding it. In order to improve performance
+ * of namespace processing, this method allows uniqueness checks
+ * to be deferred until all the namespace information is available
+ * after the entire attribute specification has been read.
+ * <p>
+ * <strong>Caution:</strong> If this method is called it should
+ * not be mixed with calls to <code>addAttribute</code> unless
+ * it has been determined that all the attribute names are unique.
+ *
+ * @param name the attribute name
+ * @param type the attribute type
+ * @param value the attribute value
+ *
+ * @see #setNonNormalizedValue
+ * @see #setSpecified
+ * @see #checkDuplicatesNS
+ */
+ public void addAttributeNS(QName name, String type, String value) {
+ int index = fLength;
+ if (fLength++ == fAttributes.length) {
+ Attribute[] attributes;
+ if (fLength < SIZE_LIMIT) {
+ attributes = new Attribute[fAttributes.length + 4];
+ }
+ else {
+ attributes = new Attribute[fAttributes.length << 1];
+ }
+ System.arraycopy(fAttributes, 0, attributes, 0, fAttributes.length);
+ for (int i = fAttributes.length; i < attributes.length; i++) {
+ attributes[i] = new Attribute();
+ }
+ fAttributes = attributes;
+ }
+
+ // set values
+ Attribute attribute = fAttributes[index];
+ attribute.name.setValues(name);
+ attribute.type = type;
+ attribute.value = value;
+ attribute.nonNormalizedValue = value;
+ attribute.specified = false;
+
+ // clear augmentations
+ attribute.augs.removeAllItems();
+ }
+
+ /**
+ * Checks for duplicate expanded names (local part and namespace name
+ * pairs) in the attribute specification. If a duplicate is found its
+ * name is returned.
+ * <p>
+ * This should be called once all the in-scope namespaces for the element
+ * enclosing these attributes is known, and after all the attributes
+ * have gone through namespace binding.
+ *
+ * @return the name of a duplicate attribute found in the search,
+ * otherwise null.
+ */
+ public QName checkDuplicatesNS() {
+ // If the list is small check for duplicates using pairwise comparison.
+ if (fLength <= SIZE_LIMIT) {
+ for (int i = 0; i < fLength - 1; ++i) {
+ Attribute att1 = fAttributes[i];
+ for (int j = i + 1; j < fLength; ++j) {
+ Attribute att2 = fAttributes[j];
+ if (att1.name.localpart == att2.name.localpart &&
+ att1.name.uri == att2.name.uri) {
+ return att2.name;
+ }
+ }
+ }
+ }
+ // If the list is large check duplicates using a hash table.
+ else {
+ // We don't want this table view to be read if someone calls
+ // addAttribute so we invalidate it up front.
+ fIsTableViewConsistent = false;
+
+ prepareTableView();
+
+ Attribute attr;
+ int bucket;
+
+ for (int i = fLength - 1; i >= 0; --i) {
+ attr = fAttributes[i];
+ bucket = getTableViewBucket(attr.name.localpart, attr.name.uri);
+
+ // The chain is stale.
+ // This must be a unique attribute.
+ if (fAttributeTableViewChainState[bucket] != fLargeCount) {
+ fAttributeTableViewChainState[bucket] = fLargeCount;
+ attr.next = null;
+ fAttributeTableView[bucket] = attr;
+ }
+ // This chain is active.
+ // We need to check if any of the attributes has the same name.
+ else {
+ // Search the table.
+ Attribute found = fAttributeTableView[bucket];
+ while (found != null) {
+ if (found.name.localpart == attr.name.localpart &&
+ found.name.uri == attr.name.uri) {
+ return attr.name;
+ }
+ found = found.next;
+ }
+
+ // Update table view
+ attr.next = fAttributeTableView[bucket];
+ fAttributeTableView[bucket] = attr;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Look up the index of an attribute by Namespace name.
+ * <p>
+ * <strong>Note:</strong>
+ * This method uses reference comparison, and thus should
+ * only be used internally. We cannot use this method in any
+ * code exposed to users as they may not pass in unique strings.
+ *
+ * @param uri The Namespace URI, or null if
+ * the name has no Namespace URI.
+ * @param localName The attribute's local name.
+ * @return The index of the attribute, or -1 if it does not
+ * appear in the list.
+ */
+ public int getIndexFast(String uri, String localPart) {
+ for (int i = 0; i < fLength; ++i) {
+ Attribute attribute = fAttributes[i];
+ if (attribute.name.localpart == localPart &&
+ attribute.name.uri == uri) {
+ return i;
+ }
+ }
+ return -1;
+ } // getIndexFast(String,String):int
+
+ /**
+ * Returns the value passed in or NMTOKEN if it's an enumerated type.
+ *
+ * @param type attribute type
+ * @return the value passed in or NMTOKEN if it's an enumerated type.
+ */
+ protected String getReportableType(String type) {
+ if (type.indexOf('(') == 0 && type.lastIndexOf(')') == type.length()-1) {
+ return "NMTOKEN";
+ }
+ return type;
+ }
+
+ /**
+ * Returns the position in the table view
+ * where the given attribute name would be hashed.
+ *
+ * @param qname the attribute name
+ * @return the position in the table view where the given attribute
+ * would be hashed
+ */
+ protected int getTableViewBucket(String qname) {
+ return (qname.hashCode() & 0x7FFFFFFF) % fTableViewBuckets;
+ }
+
+ /**
+ * Returns the position in the table view
+ * where the given attribute name would be hashed.
+ *
+ * @param localpart the local part of the attribute
+ * @param uri the namespace name of the attribute
+ * @return the position in the table view where the given attribute
+ * would be hashed
+ */
+ protected int getTableViewBucket(String localpart, String uri) {
+ if (uri == null) {
+ return (localpart.hashCode() & 0x7FFFFFFF) % fTableViewBuckets;
+ }
+ else {
+ return ((localpart.hashCode() + uri.hashCode())
+ & 0x7FFFFFFF) % fTableViewBuckets;
+ }
+ }
+
+ /**
+ * Purges all elements from the table view.
+ */
+ protected void cleanTableView() {
+ if (++fLargeCount < 0) {
+ // Overflow. We actually need to visit the chain state array.
+ if (fAttributeTableViewChainState != null) {
+ for (int i = fTableViewBuckets - 1; i >= 0; --i) {
+ fAttributeTableViewChainState[i] = 0;
+ }
+ }
+ fLargeCount = 1;
+ }
+ }
+
+ /**
+ * Prepares the table view of the attributes list for use.
+ */
+ protected void prepareTableView() {
+ if (fAttributeTableView == null) {
+ fAttributeTableView = new Attribute[fTableViewBuckets];
+ fAttributeTableViewChainState = new int[fTableViewBuckets];
+ }
+ else {
+ cleanTableView();
+ }
+ }
+
+ /**
+ * Prepares the table view of the attributes list for use,
+ * and populates it with the attributes which have been
+ * previously read.
+ */
+ protected void prepareAndPopulateTableView() {
+ prepareTableView();
+ // Need to populate the hash table with the attributes we've scanned so far.
+ Attribute attr;
+ int bucket;
+ for (int i = 0; i < fLength; ++i) {
+ attr = fAttributes[i];
+ bucket = getTableViewBucket(attr.name.rawname);
+ if (fAttributeTableViewChainState[bucket] != fLargeCount) {
+ fAttributeTableViewChainState[bucket] = fLargeCount;
+ attr.next = null;
+ fAttributeTableView[bucket] = attr;
+ }
+ else {
+ // Update table view
+ attr.next = fAttributeTableView[bucket];
+ fAttributeTableView[bucket] = attr;
+ }
+ }
+ }
//
// Classes
@@ -731,6 +1102,18 @@
/** Schema ID type. */
public boolean schemaId;
+
+ /**
+ * Augmentations information for this attribute.
+ * XMLAttributes has no knowledge if any augmentations
+ * were attached to Augmentations.
+ */
+ public Augmentations augs = new AugmentationsImpl();
+
+ // Additional data for attribute table view
+
+ /** Pointer to the next attribute in the chain. **/
+ public Attribute next;
} // class Attribute
1.7 +5 -2
xml-xerces/java/src/org/apache/xerces/impl/dtd/XMLNSDTDValidator.java
Index: XMLNSDTDValidator.java
===================================================================
RCS file:
/home/cvs/xml-xerces/java/src/org/apache/xerces/impl/dtd/XMLNSDTDValidator.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- XMLNSDTDValidator.java 29 May 2003 13:25:42 -0000 1.6
+++ XMLNSDTDValidator.java 10 Oct 2003 18:25:40 -0000 1.7
@@ -222,8 +222,11 @@
// Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
int attrCount = attributes.getLength();
for (int i = 0; i < attrCount - 1; i++) {
- String alocalpart = attributes.getLocalName(i);
String auri = attributes.getURI(i);
+ if (auri == null || auri == NamespaceContext.XMLNS_URI) {
+ continue;
+ }
+ String alocalpart = attributes.getLocalName(i);
for (int j = i + 1; j < attrCount; j++) {
String blocalpart = attributes.getLocalName(j);
String buri = attributes.getURI(j);
1.2 +5 -2
xml-xerces/java/src/org/apache/xerces/impl/dtd/XML11NSDTDValidator.java
Index: XML11NSDTDValidator.java
===================================================================
RCS file:
/home/cvs/xml-xerces/java/src/org/apache/xerces/impl/dtd/XML11NSDTDValidator.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XML11NSDTDValidator.java 2 Oct 2003 18:18:15 -0000 1.1
+++ XML11NSDTDValidator.java 10 Oct 2003 18:25:40 -0000 1.2
@@ -215,8 +215,11 @@
// Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
int attrCount = attributes.getLength();
for (int i = 0; i < attrCount - 1; i++) {
- String alocalpart = attributes.getLocalName(i);
String auri = attributes.getURI(i);
+ if (auri == null || auri == NamespaceContext.XMLNS_URI) {
+ continue;
+ }
+ String alocalpart = attributes.getLocalName(i);
for (int j = i + 1; j < attrCount; j++) {
String blocalpart = attributes.getLocalName(j);
String buri = attributes.getURI(j);
1.3 +43 -49
xml-xerces/java/src/org/apache/xerces/impl/XML11NSDocumentScannerImpl.java
Index: XML11NSDocumentScannerImpl.java
===================================================================
RCS file:
/home/cvs/xml-xerces/java/src/org/apache/xerces/impl/XML11NSDocumentScannerImpl.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- XML11NSDocumentScannerImpl.java 2 Oct 2003 18:24:15 -0000 1.2
+++ XML11NSDocumentScannerImpl.java 10 Oct 2003 18:25:40 -0000 1.3
@@ -116,10 +116,6 @@
*/
protected boolean fPerformValidation;
- protected String[] fUri = new String[4];
- protected String[] fLocalpart = new String[4];
- protected int fLength = 0;
-
// private data
//
@@ -257,7 +253,6 @@
// bind attributes (xmlns are already bound bellow)
int length = fAttributes.getLength();
- fLength = 0; //initialize structure
for (int i = 0; i < length; i++) {
fAttributes.getName(i, fAttributeQName);
@@ -270,7 +265,6 @@
//
if (fAttributeQName.uri != null
&& fAttributeQName.uri == uri) {
- checkDuplicates(fAttributeQName, fAttributes);
continue;
}
if (aprefix != XMLSymbols.EMPTY_STRING) {
@@ -286,7 +280,30 @@
XMLErrorReporter.SEVERITY_FATAL_ERROR);
}
fAttributes.setURI(i, uri);
- checkDuplicates(fAttributeQName, fAttributes);
+ }
+ }
+
+ if (length > 1) {
+ QName name = fAttributes.checkDuplicatesNS();
+ if (name != null) {
+ if (name.uri != null) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNSNotUnique",
+ new Object[] {
+ fElementQName.rawname,
+ name.localpart,
+ name.uri },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ } else {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNotUnique",
+ new Object[] {
+ fElementQName.rawname,
+ name.rawname },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
}
}
}
@@ -323,40 +340,6 @@
} // scanStartElement():boolean
- private final void checkDuplicates(
- QName qname,
- XMLAttributesImpl attributes) {
-
- // Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
- // search if such attribute already exists
- for (int i = 0; i < fLength; i++) {
- if (qname.uri == fUri[i]
- && fLocalpart[i].equals(qname.localpart)) {
- fErrorReporter.reportError(
- XMLMessageFormatter.XMLNS_DOMAIN,
- "AttributeNSNotUnique",
- new Object[] {
- fElementQName.rawname,
- qname.rawname,
- qname.uri },
- XMLErrorReporter.SEVERITY_FATAL_ERROR);
- }
- }
- int index = fLength;
- if (fLength++ == fUri.length) {
- String[] uris = new String[fUri.length + 4];
- String[] lps = new String[fUri.length + 4];
- System.arraycopy(fUri, 0, uris, 0, fUri.length);
- System.arraycopy(fLocalpart, 0, lps, 0, fLocalpart.length);
- fUri = uris;
- fLocalpart = lps;
-
- }
-
- fUri[index] = qname.uri;
- fLocalpart[index] = qname.localpart;
- }
-
/**
* Scans an attribute.
* <p>
@@ -395,15 +378,26 @@
// content
int oldLen = attributes.getLength();
- attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);
- // WFC: Unique Att Spec
- if (oldLen == attributes.getLength()) {
- reportFatalError(
- "AttributeNotUnique",
- new Object[] {
- fCurrentElement.rawname,
- fAttributeQName.rawname });
+ if (fBindNamespaces) {
+ attributes.addAttributeNS(
+ fAttributeQName,
+ XMLSymbols.fCDATASymbol,
+ null);
+ } else {
+ attributes.addAttribute(
+ fAttributeQName,
+ XMLSymbols.fCDATASymbol,
+ null);
+
+ // WFC: Unique Att Spec
+ if (oldLen == attributes.getLength()) {
+ reportFatalError(
+ "AttributeNotUnique",
+ new Object[] {
+ fCurrentElement.rawname,
+ fAttributeQName.rawname });
+ }
}
//REVISIT: one more case needs to be included: external PE and standalone
is no
1.17 +40 -16
xml-xerces/java/src/org/apache/xerces/impl/XMLNSDocumentScannerImpl.java
Index: XMLNSDocumentScannerImpl.java
===================================================================
RCS file:
/home/cvs/xml-xerces/java/src/org/apache/xerces/impl/XMLNSDocumentScannerImpl.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- XMLNSDocumentScannerImpl.java 2 Sep 2003 07:06:14 -0000 1.16
+++ XMLNSDocumentScannerImpl.java 10 Oct 2003 18:25:40 -0000 1.17
@@ -112,9 +112,9 @@
* scanner if DTD grammar is missing.*/
protected boolean fPerformValidation;
- protected String[] fUri= new String[4];
- protected String[] fLocalpart = new String[4];
- protected int fLength = 0;
+ // protected String[] fUri= new String[4];
+ // protected String[] fLocalpart = new String[4];
+ // protected int fLength = 0;
// private data
@@ -248,7 +248,7 @@
// bind attributes (xmlns are already bound bellow)
int length = fAttributes.getLength();
- fLength = 0; //initialize structure
+ // fLength = 0; //initialize structure
for (int i = 0; i < length; i++) {
fAttributes.getName(i, fAttributeQName);
@@ -258,7 +258,7 @@
// REVISIT: try removing the first "if" and see if it is faster.
//
if (fAttributeQName.uri != null && fAttributeQName.uri == uri) {
- checkDuplicates(fAttributeQName, fAttributes);
+ // checkDuplicates(fAttributeQName, fAttributes);
continue;
}
if (aprefix != XMLSymbols.EMPTY_STRING) {
@@ -270,7 +270,25 @@
XMLErrorReporter.SEVERITY_FATAL_ERROR);
}
fAttributes.setURI(i, uri);
- checkDuplicates(fAttributeQName, fAttributes);
+ // checkDuplicates(fAttributeQName, fAttributes);
+ }
+ }
+
+ if (length > 1) {
+ QName name = fAttributes.checkDuplicatesNS();
+ if (name != null) {
+ if (name.uri != null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNSNotUnique",
+ new
Object[]{fElementQName.rawname, name.localpart, name.uri},
+
XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ else {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNotUnique",
+ new
Object[]{fElementQName.rawname, name.rawname},
+
XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
}
}
}
@@ -306,7 +324,7 @@
} // scanStartElement():boolean
- private final void checkDuplicates(QName qname, XMLAttributesImpl attributes){
+ /** private final void checkDuplicates(QName qname, XMLAttributesImpl
attributes){
// Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
// search if such attribute already exists
@@ -331,7 +349,7 @@
fUri[index] = qname.uri;
fLocalpart[index] = qname.localpart;
- }
+ } **/
@@ -370,13 +388,19 @@
// content
int oldLen = attributes.getLength();
- attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);
-
- // WFC: Unique Att Spec
- if (oldLen == attributes.getLength()) {
- reportFatalError("AttributeNotUnique",
- new Object[]{fCurrentElement.rawname,
+
+ if (fBindNamespaces) {
+ attributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol,
null);
+ }
+ else {
+ attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);
+
+ // WFC: Unique Att Spec
+ if (oldLen == attributes.getLength()) {
+ reportFatalError("AttributeNotUnique",
+ new Object[]{fCurrentElement.rawname,
fAttributeQName.rawname});
+ }
}
//REVISIT: one more case needs to be included: external PE and standalone
is no
@@ -393,7 +417,7 @@
// record namespace declarations if any.
if (fBindNamespaces) {
-
+
String localpart = fAttributeQName.localpart;
String prefix = fAttributeQName.prefix != null
? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
1.30 +5 -2
xml-xerces/java/src/org/apache/xerces/impl/XMLNamespaceBinder.java
Index: XMLNamespaceBinder.java
===================================================================
RCS file:
/home/cvs/xml-xerces/java/src/org/apache/xerces/impl/XMLNamespaceBinder.java,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- XMLNamespaceBinder.java 29 May 2003 13:25:41 -0000 1.29
+++ XMLNamespaceBinder.java 10 Oct 2003 18:25:40 -0000 1.30
@@ -824,8 +824,11 @@
// Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
int attrCount = attributes.getLength();
for (int i = 0; i < attrCount - 1; i++) {
- String alocalpart = attributes.getLocalName(i);
String auri = attributes.getURI(i);
+ if (auri == null || auri == NamespaceContext.XMLNS_URI) {
+ continue;
+ }
+ String alocalpart = attributes.getLocalName(i);
for (int j = i + 1; j < attrCount; j++) {
String blocalpart = attributes.getLocalName(j);
String buri = attributes.getURI(j);
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]