// [WFC: No < in Attribute Values]
int prevPosStart = posStart + bufAbsoluteStart;
int nameStart = pos - 1 + bufAbsoluteStart;
int colonPos = -1;
char ch = buf[ pos - 1 ];
if(ch == ':' && processNamespaces) throw new XMLStreamException(
"when namespaces processing enabled colon can not be at attribute name start",
getLocation());
boolean startsWithXmlns = processNamespaces && ch == 'x';
int xmlnsPos = 0;
ch = more();
while(isNameChar(ch)) {
if(processNamespaces) {
if(startsWithXmlns && xmlnsPos < 5) {
++xmlnsPos;
if(xmlnsPos == 1) { if(ch != 'm') startsWithXmlns = false; }
else if(xmlnsPos == 2) { if(ch != 'l') startsWithXmlns = false; }
else if(xmlnsPos == 3) { if(ch != 'n') startsWithXmlns = false; }
else if(xmlnsPos == 4) { if(ch != 's') startsWithXmlns = false; }
else if(xmlnsPos == 5) {
if(ch != ':') throw new XMLStreamException(
"after xmlns in attribute name must be colon"
+"when namespaces are enabled",
getLocation());
//colonPos = pos - 1 + bufAbsoluteStart;
}
}
if(ch == ':') {
if(colonPos != -1) throw new XMLStreamException(
"only one colon is allowed in attribute name"
+" when namespaces are enabled",
getLocation());
colonPos = pos - 1 + bufAbsoluteStart;
}
}
ch = more();
}
ensureAttributesCapacity(attributeCount);
// --- start processing attributes
String name = null;
String prefix = null;
// work on prefixes and namespace URI
if(processNamespaces) {
if(xmlnsPos < 4) startsWithXmlns = false;
if(startsWithXmlns) {
if(colonPos != -1) {
//prefix = attributePrefix[ attributeCount ] = null;
name = //attributeName[ attributeCount ] =
newString(buf, colonPos - bufAbsoluteStart + 1,
//pos - 1 - (colonPos + 1 - bufAbsoluteStart)
pos - 2 - (colonPos - bufAbsoluteStart)
);
/* 07-Mar-2006, TSa: Illegal to try to (re)declare
* prefix "xmlns" (even to its correct URI)...
* (similar check for "xml" has to wait until we
* see the URI -- that can be re-declared to the
* same URI)
*/
if (name.equals("xmlns")) {
throw new XMLStreamException("trying to bind reserved NS prefix 'xmlns'",
getLocation());
}
}
} else {
if(colonPos != -1) {
prefix = attributePrefix[ attributeCount ] =
newString(buf, nameStart - bufAbsoluteStart,
//colonPos - (nameStart - bufAbsoluteStart));
colonPos - nameStart);
name = attributeName[ attributeCount ] =
newString(buf, colonPos - bufAbsoluteStart + 1,
//pos - 1 - (colonPos + 1 - bufAbsoluteStart));
pos - 2 - (colonPos - bufAbsoluteStart));
//name.substring(0, colonPos-nameStart);
} else {
prefix = attributePrefix[ attributeCount ] = null;
name = attributeName[ attributeCount ] =
newString(buf, nameStart - bufAbsoluteStart,
pos - 1 - (nameStart - bufAbsoluteStart));
}
if(!allStringsInterned) {
attributeNameHash[ attributeCount ] = name.hashCode();
}
}
} else {
// retrieve name
name = attributeName[ attributeCount ] =
newString(buf, nameStart - bufAbsoluteStart,
pos - 1 - (nameStart - bufAbsoluteStart));
////assert name != null;
if(!allStringsInterned) {
attributeNameHash[ attributeCount ] = name.hashCode();
}
}
// [25] Eq ::= S? '=' S?
while(isS(ch)) { ch = more(); } // skip additional spaces
if(ch != '=') throw new XMLStreamException(
"expected = after attribute name",
getLocation());
ch = more();
while(isS(ch)) { ch = more(); } // skip additional spaces
// [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
// | "'" ([^<&'] | Reference)* "'"
char delimit = ch;
if(delimit != '"' && delimit != '\'') throw new XMLStreamException(
"attribute value must start with quotation or apostrophe not "
+printable(delimit),
getLocation());
// parse until delimit or < and resolve Reference
//[67] Reference ::= EntityRef | CharRef
//int valueStart = pos + bufAbsoluteStart;
boolean normalizedCR = false;
usePC = false;
pcStart = pcEnd;
posStart = pos;
while(true) {
ch = more();
if(ch == delimit) {
break;
} if(ch == '<') {
throw new XMLStreamException(
"markup not allowed inside attribute value - illegal < ", getLocation());
} if(ch == '&') {
// extractEntityRef
posEnd = pos - 1;
if(!usePC) {
boolean hadCharData = posEnd > posStart;
if(hadCharData) {
// posEnd is already set correctly!!!
joinPC();
} else {
usePC = true;
pcStart = pcEnd = 0;
}
}
//assert usePC == true;
char[] resolvedEntity = parseEntityRef();
// check if replacement text can be resolved !!!
if(resolvedEntity == null) {
if(entityRefName == null) {
entityRefName = newString(buf, posStart, posEnd - posStart);
}
throw new XMLStreamException(
"could not resolve entity named '"+printable(entityRefName)+"'",
getLocation());
}
// write into PC replacement text - do merge for replacement text!!!!
for (int i = 0; i < resolvedEntity.length; i++)
{
if(pcEnd >= pc.length) ensurePC(pcEnd);
pc[pcEnd++] = resolvedEntity[ i ];
}
} else if(ch == '\t' || ch == '\n' || ch == '\r') {
// do attribute value normalization
// as described in http://www.w3.org/TR/REC-xml#AVNormalize
// TODO add test for it form spec ...
// handle EOL normalization ...
if(!usePC) {
posEnd = pos - 1;
if(posEnd > posStart) {
joinPC();
} else {
usePC = true;
pcEnd = pcStart = 0;
}
}
//assert usePC == true;
if(pcEnd >= pc.length) ensurePC(pcEnd);
if(ch != '\n' || !normalizedCR) {
pc[pcEnd++] = ' '; //'\n';
}
} else {
if(usePC) {
if(pcEnd >= pc.length) ensurePC(pcEnd);
pc[pcEnd++] = ch;
}
}
normalizedCR = ch == '\r';
}
if(processNamespaces && startsWithXmlns) {
String ns = null;
if(!usePC) {
ns = newStringIntern(buf, posStart, pos - 1 - posStart);
} else {
ns = newStringIntern(pc, pcStart, pcEnd - pcStart);
}
ensureNamespacesCapacity(namespaceEnd);
int prefixHash = -1;
/* 07-Mar-2006, TSa: It is illegal (as per XML Namespaces
* specs) to bind anything to 'xmlns' URI; and anything
* other than 'xml' to 'xml' URI...
*/
if (ns.equals(XMLConstants.XML_NS_URI)) {
if (!"xml".equals(name)) {
throw new XMLStreamException("trying to bind reserved NS URI '"+XMLConstants.XML_NS_URI+"' to prefix other than 'xml'");
}
} else if (ns.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
// Can bind nothing to this URI:
throw new XMLStreamException("trying to bind reserved NS URI '"+XMLConstants.XMLNS_ATTRIBUTE_NS_URI+"'");
}
if(colonPos != -1) {
if(ns.length() == 0) {
throw new XMLStreamException(
"non-default namespace can not be declared to be empty string (in xml 1.0)",
getLocation());
}
/* 07-Mar-2006, TSa: Can only declare 'xml' to bind to
* its standard URI -- otherwise that's an error.
*/
if (name.equals("xml")) {
if (!ns.equals(XMLConstants.XML_NS_URI)) {
throw new XMLStreamException("trying to bind reserved NS prefix 'xml' to URI other than its standard value ("+XMLConstants.XML_NS_URI+")",
getLocation());
}
}
// declare new namespace
namespacePrefix[ namespaceEnd ] = name;
if(!allStringsInterned) {
prefixHash = namespacePrefixHash[ namespaceEnd ] = name.hashCode();
}
} else {
// declare new default namespace ...
namespacePrefix[ namespaceEnd ] = null;
if(!allStringsInterned) {
prefixHash = namespacePrefixHash[ namespaceEnd ] = -1;
}
}
namespaceUri[ namespaceEnd ] = ns;
// detect duplicate namespace declarations!!!
int startNs = elNamespaceCount[ depth - 1 ];
for (int i = namespaceEnd - 1; i >= startNs; --i)
{
if(((allStringsInterned || name == null) && namespacePrefix[ i ] == name)
|| (!allStringsInterned && name != null &&
namespacePrefixHash[ i ] == prefixHash
&& name.equals(namespacePrefix[ i ])
))
{
String s = name == null ? "default" : "'"+name+"'";
throw new XMLStreamException(
"duplicated namespace declaration for "+s+" prefix", getLocation());
}
}
// ++localNamespaceEnd;
++namespaceEnd;
} else {
if(!usePC) {
attributeValue[ attributeCount ] =
new String(buf, posStart, pos - 1 - posStart);
} else {
attributeValue[ attributeCount ] =
new String(pc, pcStart, pcEnd - pcStart);
}
++attributeCount;
}
posStart = prevPosStart - bufAbsoluteStart;
return ch;
} catch (EOFException eofe) {
throw new XMLStreamException(EOF_MSG, getLocation(), eofe);
}
}