public override bool Equals(object ob) { if (ob == this) { return(true); } if (!(ob is DTDElement)) { return(false); } DTDElement other = (DTDElement)ob; if (Name == null) { if (other.Name != null) { return(false); } } else { if (!Name.Equals(other.Name)) { return(false); } } if (Attributes == null) { if (other.Attributes != null) { return(false); } } else { if (!Attributes.Equals(other.Attributes)) { return(false); } } if (Content == null) { if (other.Content != null) { return(false); } } else { if (!Content.Equals(other.Content)) { return(false); } } return(true); }
protected void ParseAttlist() { Token token = Expect(Scanner.IDENTIFIER); DTDElement element = (DTDElement)Dtd.Elements[token.Value]; DTDAttlist attlist = new DTDAttlist(token.Value); Dtd.Items.Add(attlist); if (element == null) { element = new DTDElement(token.Value); Dtd.Elements[token.Value] = element; } token = Scanner.Peek(); while (token.Type != Scanner.GT) { ParseAttdef(Scanner, element, attlist); token = Scanner.Peek(); } // MAW Version 1.17 // Prior to this version, the parser didn't actually consume the > at the // end of the ATTLIST definition. Because the parser ignored unexpected tokens // at the top level, it was ignoring the >. In parsing DOCBOOK, however, there // were two unexpected tokens, bringing this error to light. Expect(Scanner.GT); }
protected void ParseChildren(DTDElement element) { DTDContainer choiceSeq = ParseChoiceSequence(); Token token = Scanner.Peek(); choiceSeq.Cardinal = ParseCardinality(); if (token.Type == Scanner.QUES) { choiceSeq.Cardinal = DTDCardinal.ZEROONE; } else if (token.Type == Scanner.ASTERISK) { choiceSeq.Cardinal = DTDCardinal.ZEROMANY; } else if (token.Type == Scanner.PLUS) { choiceSeq.Cardinal = DTDCardinal.ONEMANY; } else { choiceSeq.Cardinal = DTDCardinal.NONE; } element.Content = choiceSeq; }
protected void ParseMixed(DTDElement element) { // MAW Version 1.19 // Keep track of whether the mixed is #PCDATA only // Don't allow * after (#PCDATA), but allow after // (#PCDATA|foo|bar|baz)* bool isPcdataOnly = true; DTDMixed mixed = new DTDMixed(); mixed.Items.Add(new DTDPCData()); Scanner.Get(); element.Content = mixed; for (;;) { Token token = Scanner.Get(); if (token.Type == Scanner.RPAREN) { token = Scanner.Peek(); if (token.Type == Scanner.ASTERISK) { Scanner.Get(); mixed.Cardinal = DTDCardinal.ZEROMANY; } else { if (!isPcdataOnly) { throw new DTDParseException(Scanner.GetUriId(), "Invalid token in Mixed content type, '*' required after (#PCDATA|xx ...): " + token.Type.Name, Scanner.GetLineNumber(), Scanner.GetColumn()); } mixed.Cardinal = DTDCardinal.NONE; } return; } if (token.Type == Scanner.PIPE) { token = Scanner.Get(); mixed.Items.Add(new DTDName(token.Value)); // MAW Ver. 1.19 isPcdataOnly = false; } else { throw new DTDParseException(Scanner.GetUriId(), "Invalid token in Mixed content type: " + token.Type.Name, Scanner.GetLineNumber(), Scanner.GetColumn()); } } }
protected void ParseElement() { Token name = Expect(Scanner.IDENTIFIER); DTDElement element = (DTDElement)Dtd.Elements[name.Value]; if (element == null) { element = new DTDElement(name.Value); Dtd.Elements[element.Name] = element; } else if (element.Content != null) { // 070501 MAW: Since the ATTLIST tag can also cause an element to be created, // only throw this exception if the element has content defined, which // won't happen when you just create an ATTLIST. Thanks to // Jags Krishnamurthy of object Edge for pointing out this problem - // originally the parser would let you define an element more than once. throw new DTDParseException(Scanner.GetUriId(), "Found second definition of element: " + name.Value, Scanner.GetLineNumber(), Scanner.GetColumn()); } Dtd.Items.Add(element); ParseContentSpec(Scanner, element); Expect(Scanner.GT); }
/** Parses the DTD file and returns a DTD object describing the DTD. * @param guessRootElement If true, tells the parser to try to guess the * root element of the document by process of elimination */ public DTD Parse(bool guessRootElement) { Token token; for (;;) { token = Scanner.Peek(); if (token.Type == Scanner.EOF) { break; } ParseTopLevelElement(); } if (guessRootElement) { Hashtable roots = new Hashtable(); foreach (DictionaryEntry de in Dtd.Elements) { DTDElement element = (DTDElement)de.Value; roots[element.Name] = element; } foreach (DictionaryEntry de in Dtd.Elements) { DTDElement element = (DTDElement)de.Value; if (!(element.Content is DTDContainer)) { continue; } //TODO: make sure this loop works. it used to be based on a java enumeration. foreach (DTDItem dtditem in ((DTDContainer)element.Content).Items) { RemoveElements(roots, Dtd, dtditem); } } if (roots.Count == 1) { IDictionaryEnumerator enumerator = roots.GetEnumerator(); enumerator.MoveNext(); Dtd.RootElement = (DTDElement)((DictionaryEntry)enumerator.Current).Value; } else { Dtd.RootElement = null; } } else { Dtd.RootElement = null; } return(Dtd); }
protected void ParseContentSpec(Scanner scanner, DTDElement element) { Token token = scanner.Get(); if (token.Type == Scanner.IDENTIFIER) { if (token.Value.Equals("EMPTY")) { element.Content = new DTDEmpty(); } else if (token.Value.Equals("ANY")) { element.Content = new DTDAny(); } else { throw new DTDParseException(scanner.GetUriId(), "Invalid token in entity content spec " + token.Value, scanner.GetLineNumber(), scanner.GetColumn()); } } else if (token.Type == Scanner.LPAREN) { token = scanner.Peek(); if (token.Type == Scanner.IDENTIFIER) { if (token.Value.Equals("#PCDATA")) { ParseMixed(element); } else { ParseChildren(element); } } else if (token.Type == Scanner.LPAREN) { ParseChildren(element); } } }
public static void TestParseDtd(string file, bool writeToLog) { try { DTDParser parser = null; // MAW Version 1.17 // If it looks like the filename may be a URL, use the URL class if (file.IndexOf("://") > 0) { parser = new DTDParser(new Uri(file), true); } else { parser = new DTDParser(file, true); } // Parse the DTD and ask the parser to guess the root element DTD dtd = parser.Parse(true); FileStream ostrm = null; StreamWriter writer = null; TextWriter oldOut = null; if (writeToLog) { oldOut = Console.Out; ostrm = new FileStream("./log.txt", FileMode.OpenOrCreate, FileAccess.Write); writer = new StreamWriter(ostrm); Console.SetOut(writer); } if (dtd.RootElement != null) { Console.WriteLine("Root element is probably: " + dtd.RootElement.Name); } foreach (DictionaryEntry de in dtd.Elements) { DTDElement elem = (DTDElement)de.Value; Console.WriteLine("Element: " + elem.Name); Console.Write(" Content: "); DumpDtdItem(elem.Content); Console.WriteLine(); if (elem.Attributes.Count > 0) { Console.WriteLine(" Attributes: "); foreach (DictionaryEntry attr_de in elem.Attributes) { Console.Write(" "); DTDAttribute attr = (DTDAttribute)attr_de.Value; DumpAttribute(attr); } Console.WriteLine(); } } foreach (DictionaryEntry de in dtd.Entities) { DTDEntity entity = (DTDEntity)de.Value; if (entity.IsParsed) { Console.Write("Parsed "); } Console.WriteLine("Entity: " + entity.Name); if (entity.Value != null) { Console.WriteLine(" Value: " + entity.Value); } if (entity.ExternalId != null) { if (entity.ExternalId is DTDSystem) { Console.WriteLine(" System: " + entity.ExternalId.System); } else { DTDPublic pub = (DTDPublic)entity.ExternalId; Console.WriteLine(" Public: " + pub.Pub + " " + pub.System); } } if (entity.Ndata != null) { Console.WriteLine(" NDATA " + entity.Ndata); } } foreach (DictionaryEntry de in dtd.Notations) { DTDNotation notation = (DTDNotation)de.Value; Console.WriteLine("Notation: " + notation.Name); if (notation.ExternalId != null) { if (notation.ExternalId is DTDSystem) { Console.WriteLine(" System: " + notation.ExternalId.System); } else { DTDPublic pub = (DTDPublic)notation.ExternalId; Console.Write(" Public: " + pub.Pub + " "); if (pub.System != null) { Console.WriteLine(pub.System); } else { Console.WriteLine(); } } } } if (writeToLog) { Console.SetOut(oldOut); writer.Close(); ostrm.Close(); } } catch (Exception exc) { Trace.WriteLine(exc.StackTrace); Console.WriteLine(exc.Message); } Console.WriteLine("Done"); Console.ReadKey(); //keep the console open }
protected void ParseAttdef(Scanner scanner, DTDElement element, DTDAttlist attlist) { Token token = Expect(Scanner.IDENTIFIER); DTDAttribute attr = new DTDAttribute(token.Value); attlist.Attributes.Add(attr); element.Attributes[token.Value] = attr; token = scanner.Get(); if (token.Type == Scanner.IDENTIFIER) { if (token.Value.Equals("NOTATION")) { attr.Type = ParseNotationList(); } else { attr.Type = token.Value; } } else if (token.Type == Scanner.LPAREN) { attr.Type = ParseEnumeration(); } token = scanner.Peek(); if (token.Type == Scanner.IDENTIFIER) { scanner.Get(); if (token.Value.Equals("#FIXED")) { attr.Decl = DTDDecl.FIXED; token = scanner.Get(); attr.DefaultValue = token.Value; } else if (token.Value.Equals("#REQUIRED")) { attr.Decl = DTDDecl.REQUIRED; } else if (token.Value.Equals("#IMPLIED")) { attr.Decl = DTDDecl.IMPLIED; } else { throw new DTDParseException(scanner.GetUriId(), "Invalid token in attribute declaration: " + token.Value, scanner.GetLineNumber(), scanner.GetColumn()); } } else if (token.Type == Scanner.STRING) { scanner.Get(); attr.Decl = DTDDecl.VALUE; attr.DefaultValue = token.Value; } }