/// <summary> /// Called once an & character is being seen. /// </summary> /// <param name="c">The next character after the & character.</param> /// <returns>The entity token.</returns> String CharacterReference(Char c) { var start = _stringBuffer.Length; var hex = false; var numeric = c == Symbols.Num; if (numeric) { c = GetNext(); hex = c == 'x' || c == 'X'; if (hex) { c = GetNext(); while (c.IsHex()) { _stringBuffer.Append(c); c = GetNext(); } } else { while (c.IsDigit()) { _stringBuffer.Append(c); c = GetNext(); } } } else if (c.IsXmlNameStart()) { do { _stringBuffer.Append(c); c = GetNext(); } while (c.IsXmlName()); } if (c == Symbols.Semicolon && _stringBuffer.Length > start) { var length = _stringBuffer.Length - start; var content = _stringBuffer.ToString(start, length); _stringBuffer.Remove(start, length); if (numeric) { var number = numeric ? content.FromHex() : content.FromDec(); if (!number.IsValidAsCharRef()) throw XmlParseError.CharacterReferenceInvalidNumber.At(_position); return number.ConvertFromUtf32(); } else { var entity = _resolver.GetSymbol(content); if (String.IsNullOrEmpty(entity)) throw XmlParseError.CharacterReferenceInvalidCode.At(_position); return entity; } } throw XmlParseError.CharacterReferenceNotTerminated.At(GetCurrentPosition()); }
protected String EReference(Char c) { var buffer = Pool.NewStringBuilder(); if (c.IsXmlNameStart()) { do { buffer.Append(c); c = _stream.Next; } while (c.IsXmlName()); var temp = buffer.ToPool(); if (temp.Length > 0 && c == Specification.SC) { var p = _container.GetEntity(temp); if (p != null) return p.NodeValue; } } else if (c == Specification.NUM) { c = _src.Next; var hex = c == 'x' || c == 'X'; if (hex) c = _stream.Next; while (hex ? c.IsHex() : c.IsDigit()) { buffer.Append(c); c = _src.Next; } var temp = buffer.ToPool(); if (temp.Length > 0 && c == Specification.SC) { var num = hex ? temp.FromHex() : temp.FromDec(); if (num.IsValidAsCharRef()) return Char.ConvertFromUtf32(num); throw Errors.Xml(ErrorCode.CharacterReferenceInvalidNumber); } } throw Errors.Xml(ErrorCode.CharacterReferenceNotTerminated); }
/// <summary> /// More http://www.w3.org/TR/REC-xml/#sec-pi. /// </summary> /// <param name="c">The next input character.</param> XmlToken ProcessingStart(Char c) { if (c.IsXmlNameStart()) { _stringBuffer.Append(c); return ProcessingTarget(GetNext(), NewProcessing()); } throw XmlParseError.XmlInvalidPI.At(GetCurrentPosition()); }
/// <summary> /// Called once an & character is being seen. /// </summary> /// <param name="c">The next character after the & character.</param> /// <returns>The entity token.</returns> XmlEntityToken CharacterReference(Char c) { if (c == Symbols.Num) { c = GetNext(); var isHex = c == 'x' || c == 'X'; if (isHex) { c = GetNext(); while (c.IsHex()) { _stringBuffer.Append(c); c = GetNext(); } } else { while (c.IsDigit()) { _stringBuffer.Append(c); c = GetNext(); } } if (_stringBuffer.Length > 0 && c == Symbols.Semicolon) return NewEntity(numeric: true, hex: isHex); } else if (c.IsXmlNameStart()) { do { _stringBuffer.Append(c); c = GetNext(); } while (c.IsXmlName()); if (c == Symbols.Semicolon) return NewEntity(); } throw XmlParseError.CharacterReferenceNotTerminated.At(GetCurrentPosition()); }
protected void PEReference(Char c, Boolean use = true) { var buffer = Pool.NewStringBuilder(); if (c.IsXmlNameStart()) { do { buffer.Append(c); c = _stream.Next; } while (c.IsXmlName()); var temp = buffer.ToPool(); if (c == Specification.SC) { var p = _container.GetParameter(temp); if (p != null) { if (use) { _stream.Push(temp, p.NodeValue); return; } else throw Errors.Xml(ErrorCode.DtdPEReferenceInvalid); } } } if (use) throw Errors.Xml(ErrorCode.DtdPEReferenceInvalid); _stringBuffer.Append(Specification.PERCENT).Append(buffer.ToString()); }
/// <summary> /// See 8.2.4.53 Before DOCTYPE name state /// </summary> /// <param name="c">The next input character.</param> XmlToken DoctypeNameBefore(Char c) { while (c.IsSpaceCharacter()) c = GetNext(); if (c.IsXmlNameStart()) { _stringBuffer.Append(c); return DoctypeName(GetNext(), NewDoctype()); } throw XmlParseError.DoctypeInvalid.At(GetCurrentPosition()); }
/// <summary> /// More http://www.w3.org/TR/REC-xml/#sec-starttags. /// </summary> /// <param name="c">The next input character.</param> XmlToken TagOpen(Char c) { if (c == Specification.EM) return MarkupDeclaration(_src.Next); if (c == Specification.QM) { c = _src.Next; if (_src.ContinuesWith(Tags.XML, false)) { _src.Advance(2); return DeclarationStart(_src.Next); } return ProcessingStart(c); } if (c == Specification.SOLIDUS) return TagEnd(_src.Next); if (c.IsXmlNameStart()) { _stringBuffer.Clear(); _stringBuffer.Append(c); return TagName(_src.Next, XmlToken.OpenTag()); } throw Errors.Xml(ErrorCode.XmlInvalidStartTag); }
/// <summary> /// More http://www.w3.org/TR/REC-xml/#sec-pi. /// </summary> /// <param name="c">The next input character.</param> DtdToken ProcessingStart(Char c) { if (c.IsXmlNameStart()) { _stringBuffer.Clear(); _stringBuffer.Append(c); return ProcessingTarget(_stream.Next, new DtdPIToken()); } throw Errors.Xml(ErrorCode.XmlInvalidPI); }
Boolean DeclarationNameBefore(Char c, DtdToken decl) { while (c.IsSpaceCharacter()) c = _stream.Next; if (c == Specification.EOF) throw Errors.Xml(ErrorCode.EOF); if (c == Specification.PERCENT) { PEReference(_stream.Next); return DeclarationNameBefore(_stream.Current, decl); } if (c.IsXmlNameStart()) { _stringBuffer.Clear(); _stringBuffer.Append(c); return DeclarationName(_stream.Next, decl); } return false; }
ElementChildrenDeclarationEntry TypeDeclarationChildren(Char c) { var entries = new List<ElementQuantifiedDeclarationEntry>(); var connection = Specification.NULL; while (true) { if (entries.Count > 0) { if (c != Specification.PIPE && c != Specification.COMMA) throw Errors.Xml(ErrorCode.DtdTypeContent); if (entries.Count == 1) connection = c; else if (connection != c) throw Errors.Xml(ErrorCode.DtdTypeContent); c = _stream.Next; } while (c.IsSpaceCharacter()) c = _stream.Next; if (c.IsXmlNameStart()) { var name = TypeDeclarationName(c); entries.Add(name); } else if (c == Specification.RBO) entries.Add(TypeDeclarationChildren(_stream.Next)); else throw Errors.Xml(ErrorCode.DtdTypeContent); c = _stream.Current; while (c.IsSpaceCharacter()) c = _stream.Next; if (c == Specification.RBC) break; } c = _stream.Next; if (entries.Count == 0) throw Errors.Xml(ErrorCode.DtdTypeInvalid); if (connection == Specification.COMMA) { var sequence = new ElementSequenceDeclarationEntry(); sequence.Sequence.AddRange(entries); sequence.Quantifier = TypeDeclarationQuantifier(c); return sequence; } else { var choice = new ElementChoiceDeclarationEntry(); choice.Choice.AddRange(entries); choice.Quantifier = TypeDeclarationQuantifier(c); return choice; } }
ElementMixedDeclarationEntry TypeDeclarationMixed(Char c) { var entry = new ElementMixedDeclarationEntry(); while (true) { while (c.IsSpaceCharacter()) c = _stream.Next; if (c == Specification.RBC) { c = _stream.Next; if (c == Specification.ASTERISK) { entry.Quantifier = ElementQuantifier.ZeroOrMore; _stream.Advance(); return entry; } if (entry.Names.Count == 0) break; } else if (c == Specification.PIPE) { c = _stream.Next; while (c.IsSpaceCharacter()) c = _stream.Next; _stringBuffer.Clear(); if (c.IsXmlNameStart()) { _stringBuffer.Append(c); while ((c = _stream.Next).IsXmlName()) _stringBuffer.Append(c); entry.Names.Add(_stringBuffer.ToString()); continue; } } throw Errors.Xml(ErrorCode.DtdTypeContent); } return entry; }
/// <summary> /// See 8.2.4.53 Before DOCTYPE name state /// </summary> /// <param name="c">The next input character.</param> XmlToken DoctypeNameBefore(Char c) { while (c.IsSpaceCharacter()) c = _src.Next; if (c.IsXmlNameStart()) { _stringBuffer.Clear(); _stringBuffer.Append(c); return DoctypeName(_src.Next, XmlToken.Doctype()); } throw Errors.Xml(ErrorCode.DoctypeInvalid); }
/// <summary> /// Called once an & character is being seen. /// </summary> /// <param name="c">The next character after the & character.</param> /// <returns>The entity token.</returns> XmlEntityToken CharacterReference(Char c) { var buffer = Pool.NewStringBuilder(); if (c == Specification.NUM) { c = _src.Next; var hex = c == 'x' || c == 'X'; if (hex) { c = _src.Next; while (c.IsHex()) { buffer.Append(c); c = _src.Next; } } else { while (c.IsDigit()) { buffer.Append(c); c = _src.Next; } } if (buffer.Length > 0 && c == Specification.SC) return new XmlEntityToken { Value = buffer.ToPool(), IsNumeric = true, IsHex = hex }; } else if (c.IsXmlNameStart()) { do { buffer.Append(c); c = _src.Next; } while (c.IsXmlName()); if (c == Specification.SC) return new XmlEntityToken { Value = buffer.ToPool() }; } buffer.ToPool(); throw Errors.Xml(ErrorCode.CharacterReferenceNotTerminated); }
/// <summary> /// More http://www.w3.org/TR/REC-xml/#NT-Attribute. /// </summary> /// <param name="c">The next input character.</param> /// <param name="tag">The current tag token.</param> XmlToken AttributeBeforeName(Char c, XmlTagToken tag) { while (c.IsSpaceCharacter()) c = _src.Next; if (c == Specification.SOLIDUS) return TagSelfClosing(_src.Next, tag); else if (c == Specification.GT) return tag; else if (c == Specification.EOF) throw Errors.Xml(ErrorCode.EOF); if (c.IsXmlNameStart()) { _stringBuffer.Clear(); _stringBuffer.Append(c); return AttributeName(_src.Next, tag); } throw Errors.Xml(ErrorCode.XmlInvalidAttribute); }
/// <summary> /// More http://www.w3.org/TR/REC-xml/#sec-starttags. /// </summary> /// <param name="c">The next input character.</param> XmlToken TagOpen(Char c) { if (c == Symbols.ExclamationMark) return MarkupDeclaration(GetNext()); if (c == Symbols.QuestionMark) { c = GetNext(); if (ContinuesWithSensitive(TagNames.Xml)) { Advance(2); return DeclarationStart(GetNext()); } return ProcessingStart(c); } if (c == Symbols.Solidus) return TagEnd(GetNext()); if (c.IsXmlNameStart()) { _stringBuffer.Append(c); return TagName(GetNext(), NewOpenTag()); } throw XmlParseError.XmlInvalidStartTag.At(GetCurrentPosition()); }
DtdToken EntityDeclarationAfter(Char c, DtdEntityToken decl) { if (c.IsSpaceCharacter()) { c = SkipSpaces(c); if (decl.IsExtern && !decl.IsParameter && String.IsNullOrEmpty(decl.ExternNotation) && _stream.ContinuesWith(NDATA)) { _stream.Advance(4); c = _stream.Next; while (c.IsSpaceCharacter()) c = _stream.Next; if (c.IsXmlNameStart()) { _stringBuffer.Clear(); do { _stringBuffer.Append(c); c = _stream.Next; } while (c.IsXmlName()); decl.ExternNotation = _stringBuffer.ToString(); return EntityDeclarationAfter(c, decl); } throw Errors.Xml(ErrorCode.DtdEntityInvalid); } } if (c == Specification.EOF) throw Errors.Xml(ErrorCode.EOF); else if (c == Specification.GT) return decl; throw Errors.Xml(ErrorCode.DtdEntityInvalid); }
/// <summary> /// More http://www.w3.org/TR/REC-xml/#dt-etag. /// </summary> /// <param name="c">The next input character.</param> XmlToken TagEnd(Char c) { if (c.IsXmlNameStart()) { do { _stringBuffer.Append(c); c = GetNext(); } while (c.IsXmlName()); while (c.IsSpaceCharacter()) c = GetNext(); if (c == Symbols.GreaterThan) { var tag = NewCloseTag(); tag.Name = FlushBuffer(); return tag; } } if (c == Symbols.EndOfFile) throw XmlParseError.EOF.At(GetCurrentPosition()); throw XmlParseError.XmlInvalidEndTag.At(GetCurrentPosition()); }
/// <summary> /// More http://www.w3.org/TR/REC-xml/#attdecls. /// </summary> /// <param name="c">The next input character.</param> DtdAttributeToken AttributeDeclaration(Char c) { var decl = new DtdAttributeToken(); if (DeclarationNameBefore(_stream.Next, decl)) { c = SkipSpaces(c); while (true) { if (c == Specification.GT) return AttributeDeclarationAfter(c, decl); else if (!c.IsXmlNameStart()) break; _stringBuffer.Clear(); decl.Attributes.Add(AttributeDeclarationName(c)); c = _stream.Current; if(c.IsSpaceCharacter()) c = SkipSpaces(c); } } throw Errors.Xml(ErrorCode.DtdAttListInvalid); }
/// <summary> /// More http://www.w3.org/TR/REC-xml/#NT-Attribute. /// </summary> /// <param name="c">The next input character.</param> /// <param name="tag">The current tag token.</param> XmlToken AttributeBeforeName(Char c, XmlTagToken tag) { while (c.IsSpaceCharacter()) c = GetNext(); if (c == Symbols.Solidus) return TagSelfClosing(GetNext(), tag); else if (c == Symbols.GreaterThan) return tag; else if (c == Symbols.EndOfFile) throw XmlParseError.EOF.At(GetCurrentPosition()); if (c.IsXmlNameStart()) { _stringBuffer.Append(c); return AttributeName(GetNext(), tag); } throw XmlParseError.XmlInvalidAttribute.At(GetCurrentPosition()); }
/// <summary> /// More http://www.w3.org/TR/REC-xml/#dt-etag. /// </summary> /// <param name="c">The next input character.</param> XmlToken TagEnd(Char c) { if (c.IsXmlNameStart()) { _stringBuffer.Clear(); do { _stringBuffer.Append(c); c = _src.Next; } while (c.IsXmlName()); while (c.IsSpaceCharacter()) c = _src.Next; if (c == Specification.GT) { var tag = XmlToken.CloseTag(); tag.Name = _stringBuffer.ToString(); return tag; } } if (c == Specification.EOF) throw Errors.Xml(ErrorCode.EOF); throw Errors.Xml(ErrorCode.XmlInvalidEndTag); }