private bool ParseAttributeValueChunk()
{
char[] chars = _ps.chars;
int pos = _ps.charPos;
_curNode = AddNode(_index + _attrCount + 1, _index + 2);
_curNode.SetLineInfo(_ps.LineNo, _ps.LinePos);
if (_emptyEntityInAttributeResolved)
{
_curNode.SetValueNode(XmlNodeType.Text, string.Empty);
_emptyEntityInAttributeResolved = false;
return true;
}
Debug.Assert(_stringBuilder.Length == 0);
for (;;)
{
unsafe
{
while (_xmlCharType.IsAttributeValueChar(chars[pos]))
pos++;
}
switch (chars[pos])
{
// eol D
case (char)0xD:
Debug.Assert(_ps.eolNormalized, "Entity replacement text for attribute values should be EOL-normalized!");
pos++;
continue;
// eol A, tab
case (char)0xA:
case (char)0x9:
if (_normalize)
{
chars[pos] = (char)0x20; // CDATA normalization of 0xA and 0x9
}
pos++;
continue;
case '"':
case '\'':
case '>':
pos++;
continue;
// attribute values cannot contain '<'
case '<':
Throw(pos, SR.Xml_BadAttributeChar, XmlException.BuildCharExceptionArgs('<', '\0'));
break;
// entity reference
case '&':
if (pos - _ps.charPos > 0)
{
_stringBuilder.Append(chars, _ps.charPos, pos - _ps.charPos);
}
_ps.charPos = pos;
// expand char entities but not general entities
switch (HandleEntityReference(true, EntityExpandType.OnlyCharacter, out pos))
{
case EntityType.CharacterDec:
case EntityType.CharacterHex:
case EntityType.CharacterNamed:
chars = _ps.chars;
if (_normalize && _xmlCharType.IsWhiteSpace(chars[_ps.charPos]) && pos - _ps.charPos == 1)
{
chars[_ps.charPos] = (char)0x20; // CDATA normalization of character references in entities
}
break;
case EntityType.Unexpanded:
if (_stringBuilder.Length == 0)
{
_curNode.lineInfo.linePos++;
_ps.charPos++;
_curNode.SetNamedNode(XmlNodeType.EntityReference, ParseEntityName());
return true;
}
else
{
goto ReturnText;
}
default:
Debug.Assert(false, "We should never get to this point.");
break;
}
chars = _ps.chars;
continue;
default:
// end of buffer
if (pos == _ps.charsUsed)
{
goto ReadData;
}
// surrogate chars
else
{
char ch = chars[pos];
if (XmlCharType.IsHighSurrogate(ch))
{
if (pos + 1 == _ps.charsUsed)
{
goto ReadData;
}
pos++;
if (XmlCharType.IsLowSurrogate(chars[pos]))
{
pos++;
continue;
}
}
ThrowInvalidChar(chars, _ps.charsUsed, pos);
break;
}
}
ReadData:
if (pos - _ps.charPos > 0)
{
_stringBuilder.Append(chars, _ps.charPos, pos - _ps.charPos);
_ps.charPos = pos;
}
// read new characters into the buffer
if (ReadData() == 0)
{
if (_stringBuilder.Length > 0)
{
goto ReturnText;
}
else
{
if (HandleEntityEnd(false))
{
SetupEndEntityNodeInAttribute();
return true;
}
else
{
Debug.Assert(false, "We should never get to this point.");
}
}
}
pos = _ps.charPos;
chars = _ps.chars;
}
ReturnText:
if (pos - _ps.charPos > 0)
{
_stringBuilder.Append(chars, _ps.charPos, pos - _ps.charPos);
_ps.charPos = pos;
}
_curNode.SetValueNode(XmlNodeType.Text, _stringBuilder.ToString());
_stringBuilder.Length = 0;
return true;
}