- }
-
- private void ReadIgnoreSect ()
- {
- bool skip = false;
- SkipWhitespace ();
- Expect ('[');
- int dtdIgnoreSect = 1;
- while (dtdIgnoreSect > 0) {
- switch (skip ? PeekChar () : ReadChar ()) {
- case -1:
- throw new XmlException (this as IXmlLineInfo,"Unexpected IGNORE section end.");
- case '<':
- if (ReadChar () == '!' && ReadChar () == '[')
- dtdIgnoreSect++;
- break;
- case ']':
- if (ReadChar () == ']') {
- if (ReadChar () == '>')
- dtdIgnoreSect--;
- else
- skip = true;
- }
- break;
- }
- skip = false;
- }
- }
-
- // The reader is positioned on the head of the name.
- private DTDElementDeclaration ReadElementDecl ()
- {
- DTDElementDeclaration decl = new DTDElementDeclaration (DTD);
- SkipWhitespace ();
- TryExpandPERef ();
- decl.Name = ReadName ();
- SkipWhitespace ();
- TryExpandPERef ();
- ReadContentSpec (decl);
- SkipWhitespace ();
- // This expanding is only allowed as a non-validating parser.
- TryExpandPERef ();
- Expect ('>');
- return decl;
- }
-
- // read 'children'(BNF) of contentspec
- private void ReadContentSpec (DTDElementDeclaration decl)
- {
- switch(PeekChar ())
- {
- case 'E':
- decl.IsEmpty = true;
- Expect ("EMPTY");
- break;
- case 'A':
- decl.IsAny = true;
- Expect ("ANY");
- break;
- case '(':
- DTDContentModel model = decl.ContentModel;
- ReadChar ();
- SkipWhitespace ();
- TryExpandPERef ();
- if(PeekChar () == '#') {
- // Mixed Contents. "#PCDATA" must appear first.
- decl.IsMixedContent = true;
- Expect ("#PCDATA");
- SkipWhitespace ();
- TryExpandPERef ();
- SkipWhitespace ();
- while(PeekChar () != ')') {
- Expect('|');
- SkipWhitespace ();
- TryExpandPERef ();
- SkipWhitespace ();
- DTDContentModel elem = new DTDContentModel (DTD, decl.Name);
- model.ElementName = ReadName ();
- model.ChildModels.Add (elem);
- SkipWhitespace ();
- TryExpandPERef ();
- }
- Expect (')');
- if (model.ChildModels.Count > 0) {
- Expect ('*');
- model.Occurence = DTDOccurence.ZeroOrMore;
- }
- else if (PeekChar () == '*')
- Expect ('*');
- } else {
- // Non-Mixed Contents
- model.ChildModels.Add (ReadCP (decl));
- SkipWhitespace ();
-
- do { // copied from ReadCP() ...;-)
- TryExpandPERef ();
- SkipWhitespace ();
- if(PeekChar ()=='|') {
- // CPType=Or
- model.OrderType = DTDContentOrderType.Or;
- ReadChar ();
- SkipWhitespace ();
- model.ChildModels.Add (ReadCP (decl));
- SkipWhitespace ();
- }
- else if(PeekChar () == ',')
- {
- // CPType=Seq
- model.OrderType = DTDContentOrderType.Seq;
- ReadChar ();
- SkipWhitespace ();
- model.ChildModels.Add (ReadCP (decl));
- SkipWhitespace ();
- }
- else
- break;
- }
- while(true);
-
- Expect (')');
- switch(PeekChar ())
- {
- case '?':
- model.Occurence = DTDOccurence.Optional;
- ReadChar ();
- break;
- case '*':
- model.Occurence = DTDOccurence.ZeroOrMore;
- ReadChar ();
- break;
- case '+':
- model.Occurence = DTDOccurence.OneOrMore;
- ReadChar ();
- break;
- }
- SkipWhitespace ();
- }
- SkipWhitespace ();
- break;
- }
- }
-
- // Read 'cp' (BNF) of contentdecl (BNF)
- private DTDContentModel ReadCP (DTDElementDeclaration elem)
- {
- DTDContentModel model = null;
- TryExpandPERef ();
- if(PeekChar () == '(') {
- model = new DTDContentModel (DTD, elem.Name);
- ReadChar ();
- SkipWhitespace ();
- model.ChildModels.Add (ReadCP (elem));
- SkipWhitespace ();
- do {
- TryExpandPERef ();
- SkipWhitespace ();
- if(PeekChar ()=='|') {
- // CPType=Or
- model.OrderType = DTDContentOrderType.Or;
- ReadChar ();
- SkipWhitespace ();
- model.ChildModels.Add (ReadCP (elem));
- SkipWhitespace ();
- }
- else if(PeekChar () == ',') {
- // CPType=Seq
- model.OrderType = DTDContentOrderType.Seq;
- ReadChar ();
- SkipWhitespace ();
- model.ChildModels.Add (ReadCP (elem));
- SkipWhitespace ();
- }
- else
- break;
- }
- while(true);
- SkipWhitespace ();
- Expect (')');
- }
- else {
- TryExpandPERef ();
- model = new DTDContentModel (DTD, elem.Name);
- model.ElementName = ReadName ();
- }
-
- switch(PeekChar ()) {
- case '?':
- model.Occurence = DTDOccurence.Optional;
- ReadChar ();
- break;
- case '*':
- model.Occurence = DTDOccurence.ZeroOrMore;
- ReadChar ();
- break;
- case '+':
- model.Occurence = DTDOccurence.OneOrMore;
- ReadChar ();
- break;
- }
- return model;
- }
-
- // The reader is positioned on the first name char.
- private void ReadParameterEntityDecl ()
- {
- DTDParameterEntityDeclaration decl =
- new DTDParameterEntityDeclaration();
- decl.BaseURI = BaseURI;
-
- decl.Name = ReadName ();
- SkipWhitespace ();
-
- if (PeekChar () == 'S' || PeekChar () == 'P') {
-// throw new NotImplementedException ("External parameter entity reference is not implemented yet.");
- // read publicId/systemId
- ReadExternalID ();
- decl.PublicId = attributes ["PUBLIC"] as string;
- decl.SystemId = attributes ["SYSTEM"] as string;
- SkipWhitespace ();
- }
- else {
- TryExpandPERef ();
- int quoteChar = ReadChar ();
- int start = currentTag.Length;
- while (true) {
- SkipWhitespace ();
- int c = PeekChar ();
- if ((int) c == -1)
- throw new XmlException ("unexpected end of stream in entity value definition.");
- switch (c) {
- case '"':
- ReadChar ();
- if (quoteChar == '"') goto SKIP;
- break;
- case '\'':
- ReadChar ();
- if (quoteChar == '\'') goto SKIP;
- break;
- case '%':
- ImportAsPERef ();
- break;
- default:
- ReadChar ();
- break;
- }
- }
- SKIP:
- decl.Value = currentTag.ToString (start, currentTag.Length - start - 1);
- }
- SkipWhitespace ();
- Expect ('>');
- if (parameterEntities [decl.Name] == null) {
- parameterEntities.Add (decl.Name, decl);
- }
- }
-
- // reader is positioned on '%'
- private void ImportAsPERef ()
- {
- StringBuilder sb = null;
- int peRefStart = currentTag.Length;
- string appendStr = "";
- ReadChar ();
- string peName = ReadName ();
- Expect (';');
- DTDParameterEntityDeclaration peDecl =
- this.parameterEntities [peName] as DTDParameterEntityDeclaration;
- if (peDecl == null)
- throw new XmlException (this as IXmlLineInfo,"Parameter entity " + peName + " not found.");
- if (peDecl.SystemId != null) {
- PushParserInput (peDecl.SystemId);
- if (sb == null)
- sb = new StringBuilder ();
- else
- sb.Length = 0;
- while (PeekChar () != -1)
- sb.Append (ReadChar ());
- PopParserInput ();
- appendStr = sb.ToString ();
- } else {
- appendStr = peDecl.Value;
- }
- currentTag.Remove (peRefStart,
- currentTag.Length - peRefStart);
- currentTag.Append (Dereference (appendStr));
- }
-
- // The reader is positioned on the head of the name.
- private DTDEntityDeclaration ReadEntityDecl ()
- {
- DTDEntityDeclaration decl = new DTDEntityDeclaration ();
- decl.IsInternalSubset = isIntSubset;
- decl.Name = ReadName ();
- SkipWhitespace ();
- TryExpandPERef ();
- SkipWhitespace ();
-
- if (PeekChar () == 'S' || PeekChar () == 'P') {
- // external entity
- ReadExternalID ();
- decl.PublicId = attributes ["PUBLIC"] as string;
- decl.SystemId = attributes ["SYSTEM"] as string;
- if (SkipWhitespace ()) {
- if (PeekChar () == 'N') {
- // NDataDecl
- Expect ("NDATA");
- if (SkipWhitespace ())
- decl.NotationName = ReadName (); // ndata_name
- }
- }
- }
- else {
- // general entity
- decl.EntityValue = ReadEntityValueDecl ();
- }
- SkipWhitespace ();
- // This expanding is only allowed as a non-validating parser.
- TryExpandPERef ();
- Expect ('>');
- return decl;
- }
-
- private string ReadEntityValueDecl ()
- {
- SkipWhitespace ();
- // quotation char will be finally removed on unescaping
- int quoteChar = ReadChar ();
- int start = currentTag.Length;
- if (quoteChar != '\'' && quoteChar != '"')
- throw new XmlException ("quotation char was expected.");
-
- while (PeekChar () != quoteChar) {
- switch (PeekChar ()) {
- case '%':
- this.ImportAsPERef ();
- continue;
- case '&':
- ReadChar ();
- ReadReference (true);
- break;
- case -1:
- throw new XmlException ("unexpected end of stream.");
- default:
- ReadChar ();
- break;
- }
- }
- string value = Dereference (currentTag.ToString (start, currentTag.Length - start));
- Expect (quoteChar);
- return value;
- }
-
- private DTDAttListDeclaration ReadAttListDecl ()
- {
- SkipWhitespace ();
- TryExpandPERef ();
- string name = ReadName (); // target element name
- DTDAttListDeclaration decl =
- DTD.AttListDecls [name] as DTDAttListDeclaration;
- if (decl == null)
- decl = new DTDAttListDeclaration ();
- decl.Name = name;
-
- SkipWhitespace ();
- TryExpandPERef ();
- SkipWhitespace ();
-
- while (XmlConstructs.IsName ((char) PeekChar ())) {
- DTDAttributeDefinition def = ReadAttributeDefinition ();
- if (decl [def.Name] == null)
- decl.Add (def);
- SkipWhitespace ();
- TryExpandPERef ();
- SkipWhitespace ();
- }
- SkipWhitespace ();
- // This expanding is only allowed as a non-validating parser.
- TryExpandPERef ();
- Expect ('>');
- return decl;
- }
-
- private DTDAttributeDefinition ReadAttributeDefinition ()
- {
- DTDAttributeDefinition def = new DTDAttributeDefinition ();
-
- // attr_name
- TryExpandPERef ();
- def.Name = ReadName ();
- SkipWhitespace ();
-
- // attr_value
- TryExpandPERef ();
- switch(PeekChar ()) {
- case 'C': // CDATA
- Expect ("CDATA");
- def.Datatype = XmlSchemaDatatype.FromName ("normalizedString");
- break;
- case 'I': // ID, IDREF, IDREFS
- Expect ("ID");
- if(PeekChar () == 'R') {
- Expect ("REF");
- if(PeekChar () == 'S') {
- // IDREFS
- ReadChar ();
- def.Datatype = XmlSchemaDatatype.FromName ("IDREFS");
- }
- else // IDREF
- def.Datatype = XmlSchemaDatatype.FromName ("IDREF");
- }
- else // ID
- def.Datatype = XmlSchemaDatatype.FromName ("ID");
- break;
- case 'E': // ENTITY, ENTITIES
- Expect ("ENTIT");
- switch(ReadChar ()) {
- case 'Y': // ENTITY
- def.Datatype = XmlSchemaDatatype.FromName ("ENTITY");
- break;
- case 'I': // ENTITIES
- Expect ("ES");
- def.Datatype = XmlSchemaDatatype.FromName ("ENTITIES");
- break;
- }
- break;
- case 'N': // NMTOKEN, NMTOKENS, NOTATION
- ReadChar ();
- switch(PeekChar ()) {
- case 'M':
- Expect ("MTOKEN");
- if(PeekChar ()=='S') { // NMTOKENS
- ReadChar ();
- def.Datatype = XmlSchemaDatatype.FromName ("NMTOKENS");
- }
- else // NMTOKEN
- def.Datatype = XmlSchemaDatatype.FromName ("NMTOKEN");
- break;
- case 'O':
- Expect ("OTATION");
- def.Datatype = XmlSchemaDatatype.FromName ("NOTATION");
- SkipWhitespace ();
- Expect ('(');
- SkipWhitespace ();
- def.EnumeratedNotations.Add (ReadName ()); // notation name
- SkipWhitespace ();
- while(PeekChar () == '|') {
- ReadChar ();
- SkipWhitespace ();
- def.EnumeratedNotations.Add (ReadName ()); // notation name
- SkipWhitespace ();
- }
- Expect (')');
- break;
- default:
- throw new XmlException ("attribute declaration syntax error.");
- }
- break;
- default: // Enumerated Values
- TryExpandPERef ();
- Expect ('(');
- SkipWhitespace ();
- def.EnumeratedAttributeDeclaration.Add (ReadNmToken ()); // enum value
- SkipWhitespace ();
- while(PeekChar () == '|') {
- ReadChar ();
- SkipWhitespace ();
- def.EnumeratedAttributeDeclaration.Add (ReadNmToken ()); // enum value
- SkipWhitespace ();
- }
- Expect (')');
- break;
- }
- SkipWhitespace ();
-
- TryExpandPERef ();
-
- // def_value
- if(PeekChar () == '#')
- {
- ReadChar ();
- switch(PeekChar ())
- {
- case 'R':
- Expect ("REQUIRED");
- def.OccurenceType = DTDAttributeOccurenceType.Required;
- break;
- case 'I':
- Expect ("IMPLIED");
- def.OccurenceType = DTDAttributeOccurenceType.Optional;
- break;
- case 'F':
- Expect ("FIXED");
- def.OccurenceType = DTDAttributeOccurenceType.Fixed;
- SkipWhitespace ();
- def.UnresolvedDefaultValue = ReadAttribute ();
- break;
- }
- } else {
- // one of the enumerated value
- if (PeekChar () == -1) {
- PopParserInput ();
- }
- SkipWhitespace ();
- def.UnresolvedDefaultValue = ReadAttribute ();
- }
-
- return def;
- }
-
- private DTDNotationDeclaration ReadNotationDecl()
- {
- DTDNotationDeclaration decl = new DTDNotationDeclaration ();
- SkipWhitespace ();
- decl.Name = ReadName (); // notation name
- if (namespaces) { // copy from SetProperties ;-)
- int indexOfColon = decl.Name.IndexOf (':');
-
- if (indexOfColon == -1) {
- decl.Prefix = String.Empty;
- decl.LocalName = decl.Name;
- } else {
- decl.Prefix = decl.Name.Substring (0, indexOfColon);
- decl.LocalName = decl.Name.Substring (indexOfColon + 1);
- }
- } else {
- decl.Prefix = String.Empty;
- decl.LocalName = decl.Name;
- }
-
- SkipWhitespace ();
- if(PeekChar () == 'P') {
- decl.PublicId = ReadPubidLiteral ();
- SkipWhitespace ();
- if (PeekChar () == '\'' || PeekChar () == '"') {
- decl.SystemId = ReadSystemLiteral (false);
- SkipWhitespace ();
- }
- } else if(PeekChar () == 'S') {
- decl.SystemId = ReadSystemLiteral (true);
- SkipWhitespace ();
- }
- if(decl.PublicId == null && decl.SystemId == null)
- throw new XmlException ("public or system declaration required for \"NOTATION\" declaration.");
- // This expanding is only allowed as a non-validating parser.
- TryExpandPERef ();
- Expect ('>');
- return decl;
- }
-
- private void TryExpandPERef ()
- {
- if (PeekChar () == '%') {
- ReadChar ();
- if (!XmlConstructs.IsName (PeekChar ()))
- return;
- ExpandPERef ();
- }
- }
-
- // reader is positioned on the first letter of the name.
- private void ExpandPERef ()
- {
- ExpandPERef (true);
- }
-
- private void ExpandPERef (bool attachSpace)
- {
- string peName = ReadName ();
- Expect (";");
- ExpandNamedPERef (peName, attachSpace);
- }
-
- private void ExpandNamedPERef (string peName, bool attachSpace)
- {
- DTDParameterEntityDeclaration decl =
- parameterEntities [peName] as DTDParameterEntityDeclaration;
- if (decl == null)
- throw new XmlException ("undeclared parameter entity: '" + peName + "'");
- if (decl.SystemId != null) {
- PushParserInput (decl.SystemId);
- }
- // add buffer
- else
- currentInput.InsertParameterEntityBuffer (attachSpace ? " " + Dereference (decl.Value) + " " : decl.Value);
- SkipWhitespace (); // is it ok?
-// while (PeekChar () == '%')
-// TryExpandPERef (); // recursive
- }
-
- private void ReadExternalID() {
- switch(PeekChar ()) {
- case 'S':
- attributes ["PUBLIC"] = null;
- attributes ["SYSTEM"] = ReadSystemLiteral (true);
- break;
- case 'P':
- attributes ["PUBLIC"] = ReadPubidLiteral ();
- SkipWhitespace ();
- attributes ["SYSTEM"] = ReadSystemLiteral (false);
- break;
- }
- }
-
- // The reader is positioned on the first 'S' of "SYSTEM".
- private string ReadSystemLiteral (bool expectSYSTEM)
- {
- if(expectSYSTEM)
- Expect ("SYSTEM");
- SkipWhitespace ();
- int quoteChar = ReadChar (); // apos or quot
- int startPos = currentTag.Length;
- int c = 0;
- while(c != quoteChar) {
- c = ReadChar ();
- if(c < 0) throw new XmlException (this as IXmlLineInfo,"Unexpected end of stream in ExternalID.");
- }
- return currentTag.ToString (startPos, currentTag.Length - 1 - startPos);
- }
-
- private string ReadPubidLiteral()
- {
- Expect ("PUBLIC");
- SkipWhitespace ();
- int quoteChar = ReadChar ();
- int startPos = currentTag.Length;
- int c = 0;
- while(c != quoteChar)
- {
- c = ReadChar ();
- if(c < 0) throw new XmlException (this as IXmlLineInfo,"Unexpected end of stream in ExternalID.");
- if(c != quoteChar && !XmlConstructs.IsPubid (c))
- throw new XmlException (this as IXmlLineInfo,"character '" + (char)c + "' not allowed for PUBLIC ID");
- }
- return currentTag.ToString (startPos, currentTag.Length - 1 - startPos);