private void InferContent(RelaxngElement ct, bool isNew) { source.Read(); source.MoveToContent(); switch (source.NodeType) { case XmlNodeType.EndElement: InferAsEmptyElement(ct, isNew); break; case XmlNodeType.Element: InferComplexContent(ct, isNew); break; case XmlNodeType.Text: case XmlNodeType.CDATA: case XmlNodeType.SignificantWhitespace: InferTextContent(ct, isNew); source.MoveToContent(); if (source.NodeType == XmlNodeType.Element) { goto case XmlNodeType.Element; } break; case XmlNodeType.Whitespace: InferContent(ct, isNew); // skip and retry break; } }
private void InferComplexContent(RelaxngElement ct, bool isNew) { bool makeMixed = false; RelaxngPattern content = GetElementContent(ct); if (content != null) { switch (content.PatternType) { case RelaxngPatternType.Text: case RelaxngPatternType.Data: makeMixed = true; ct.Patterns.Remove(content); ct.Patterns.Add(new RelaxngGroup()); break; } } else { ct.Patterns.Add(new RelaxngGroup()); } InferComplexContentCore(ct, isNew); if (makeMixed) { MarkAsMixed(ct); } }
private void InferElement(RelaxngDefine el, bool isNew) { RelaxngElement ct = (RelaxngElement)el.Patterns [0]; // Attributes if (source.MoveToFirstAttribute()) { InferAttributes(ct, isNew); source.MoveToElement(); } // Content if (source.IsEmptyElement) { InferAsEmptyElement(ct, isNew); source.Read(); source.MoveToContent(); } else { InferContent(ct, isNew); source.ReadEndElement(); } if (GetElementContent(ct) == null) { el.Patterns.Add(new RelaxngEmpty()); } }
public void WriteElement(RelaxngElement element) { w.Write("element "); element.NameClass.WriteRnc(this); w.Write(" {"); WritePatterns(element.Patterns, false); w.Write("}"); }
RelaxngPattern CreateElement(XmlSchemaElement xse) { if (xse.RefName != XmlQualifiedName.Empty) { RelaxngRef r = new RelaxngRef(); r.Name = xse.RefName.Name; // namespace means nothing here. return(r); } RelaxngElement re = new RelaxngElement(); RelaxngName name = new RelaxngName(); name.LocalName = xse.Name; re.NameClass = name; XmlSchemaComplexType ct = xse.SchemaType as XmlSchemaComplexType; foreach (XmlSchemaAttribute a in ct.Attributes) { re.Patterns.Add(CreateAttribute(a)); } RelaxngPattern rpart; if (ct.Particle == null) { rpart = new RelaxngEmpty(); } else { rpart = CreatePatternFromParticle(ct.Particle); } if (ct.IsMixed) { if (rpart.PatternType != RelaxngPatternType.Empty) { RelaxngMixed mixed = new RelaxngMixed(); mixed.Patterns.Add(rpart); rpart = mixed; } else { rpart = new RelaxngText(); } } re.Patterns.Add(rpart); return(re); }
private void InferTextContent(RelaxngElement ct, bool isNew) { string value = source.ReadString(); RelaxngPattern p = GetElementContent(ct); if (p == null) { ct.Patterns.Add(CreateSimplePattern( InferSimpleType(value))); return; } RelaxngPatternList pl = null; switch (p.PatternType) { case RelaxngPatternType.Text: case RelaxngPatternType.Data: return; // no way to narrow it to data. case RelaxngPatternType.Empty: ct.Patterns.Remove(p); ct.Patterns.Add(new RelaxngText()); return; case RelaxngPatternType.Group: pl = ((RelaxngBinaryContentPattern)p).Patterns; break; case RelaxngPatternType.Optional: case RelaxngPatternType.ZeroOrMore: case RelaxngPatternType.OneOrMore: pl = ((RelaxngSingleContentPattern)p).Patterns; break; default: throw Error(p, "Unexpected pattern"); } if (pl.Count > 0 && pl [0] is RelaxngMixed) { return; } RelaxngMixed m = new RelaxngMixed(); while (pl.Count > 0) { RelaxngPattern child = pl [0]; m.Patterns.Add(child); pl.Remove(child); } pl.Add(m); }
// Already relaxed. private RelaxngDefine CreateGlobalElement(QName name) { RelaxngDefine def = new RelaxngDefine(); def.Name = CreateUniqueName(name.Name); RelaxngElement el = new RelaxngElement(); el.NameClass = new RelaxngName(name.Name, name.Namespace); def.Patterns.Add(el); elements.Add(name, def); grammar.Defines.Add(def); return(def); }
// Change pattern as to allow text content. private void MarkAsMixed(RelaxngElement ct) { RelaxngPattern p = GetElementContent(ct); // empty if (p == null || p is RelaxngEmpty) { if (p != null) { ct.Patterns.Remove(p); } ct.Patterns.Add(new RelaxngText()); return; } // text switch (p.PatternType) { case RelaxngPatternType.Text: case RelaxngPatternType.Data: case RelaxngPatternType.Mixed: return; case RelaxngPatternType.Choice: case RelaxngPatternType.Group: RelaxngBinaryContentPattern b = (RelaxngBinaryContentPattern)p; if (b != null) { RelaxngMixed m = b.Patterns [0] as RelaxngMixed; if (m == null) { m = new RelaxngMixed(); while (b.Patterns.Count > 0) { RelaxngPattern child = b.Patterns [0]; m.Patterns.Add(child); b.Patterns.Remove(child); } b.Patterns.Add(m); } } break; default: throw Error(p, "Not allowed pattern."); } }
private RelaxngPattern GetElementContent(RelaxngElement el) { if (el.Patterns.Count == 0) { return(null); } RelaxngPattern p = el.Patterns [0]; if (p is RelaxngInterleave) { return(el.Patterns.Count == 2 ? el.Patterns [1] : null); } else { return(p); } }
// Note that it does not return the changed sequence. private RelaxngSingleContentPattern ToSequenceOfChoice( RelaxngElement ct, RelaxngGroup s) { RelaxngSingleContentPattern scp = laxOccurence ? (RelaxngSingleContentPattern) new RelaxngZeroOrMore() : new RelaxngOneOrMore(); RelaxngChoice c = new RelaxngChoice(); foreach (RelaxngPattern p in s.Patterns) { c.Patterns.Add(p); } scp.Patterns.Add(c); ct.Patterns.Clear(); ct.Patterns.Add(scp); return(scp); }
private RngInference(XmlReader xmlReader, RelaxngGrammar grammar, bool laxOccurence, bool laxTypeInference) { this.source = xmlReader; this.grammar = grammar; this.laxOccurence = laxOccurence; this.laxTypeInference = laxTypeInference; nsmgr = new XmlNamespaceManager(source.NameTable); foreach (RelaxngDefine def in grammar.Defines) { if (def.Patterns.Count != 1) { continue; } RelaxngElement e = def.Patterns [0] as RelaxngElement; RelaxngAttribute a = def.Patterns [0] as RelaxngAttribute; if (e == null && a == null) { continue; } RelaxngName rn = e != null ? e.NameClass as RelaxngName : a.NameClass as RelaxngName; if (rn == null) { continue; } QName qname = new QName(rn.LocalName, rn.Namespace); if (e != null) { elements.Add(qname, def); } else { attributes.Add(qname, def); } } }
private void InferAsEmptyElement(RelaxngElement ct, bool isNew) { RelaxngPattern content = GetElementContent(ct); if (content == null) { ct.Patterns.Add(new RelaxngEmpty()); return; } RelaxngGroup g = content as RelaxngGroup; if (g == null) { return; } RelaxngOptional opt = new RelaxngOptional(); opt.Patterns.Add(g); ct.Patterns.Remove(content); ct.Patterns.Add(opt); }
private void ProcessSequence(RelaxngElement ct, RelaxngGroup s, ref int position, ref bool consumed, bool isNew) { RelaxngMixed m = s.Patterns.Count > 0 ? s.Patterns [0] as RelaxngMixed : null; RelaxngPatternList pl = m != null ? m.Patterns : s.Patterns; for (int i = 0; i < position; i++) { RelaxngPattern p = pl [i]; RelaxngRef iel = p as RelaxngRef; if (iel == null) { RelaxngOneOrMore oom = p as RelaxngOneOrMore; iel = (RelaxngRef)oom.Patterns [0]; } if (ElementMatches(iel)) { // Sequence element type violation // might happen (might not, but we // cannot backtrack here). So switch // to sequence of choice* here. ProcessLax(ToSequenceOfChoice(ct, s)); return; } } if (pl.Count <= position) { QName name = new QName(source.LocalName, source.NamespaceURI); RelaxngDefine nel = GetGlobalElement(name); if (nel != null) { InferElement(nel, false); } else { nel = CreateGlobalElement(name); // used to be CreateElement(). InferElement(nel, true); } RelaxngRef re = new RelaxngRef(); re.Name = nel.Name; pl.Add(re); consumed = true; return; } RelaxngPattern c = pl [position]; RelaxngRef el = c as RelaxngRef; if (el == null) { RelaxngOneOrMore oom = c as RelaxngOneOrMore; el = (RelaxngRef)oom.Patterns [0]; } if (el == null) { throw Error(s, String.Format("Target complex type content sequence has an unacceptable type of particle {0}", s.Patterns [position])); } bool matches = ElementMatches(el); if (matches) { if (consumed && c is RelaxngRef) { RelaxngOneOrMore oom = new RelaxngOneOrMore(); oom.Patterns.Add(el); pl [position] = oom; } InferElement(el, false); source.MoveToContent(); switch (source.NodeType) { case XmlNodeType.None: if (source.NodeType == XmlNodeType.Element) { goto case XmlNodeType.Element; } else if (source.NodeType == XmlNodeType.EndElement) { goto case XmlNodeType.EndElement; } break; case XmlNodeType.Element: ProcessSequence(ct, s, ref position, ref consumed, isNew); break; case XmlNodeType.Text: case XmlNodeType.CDATA: case XmlNodeType.SignificantWhitespace: MarkAsMixed(ct); source.ReadString(); goto case XmlNodeType.None; case XmlNodeType.Whitespace: source.ReadString(); goto case XmlNodeType.None; case XmlNodeType.EndElement: return; default: source.Read(); break; } } else { if (consumed) { position++; consumed = false; ProcessSequence(ct, s, ref position, ref consumed, isNew); } else { ProcessLax(ToSequenceOfChoice(ct, s)); } } }
private void InferComplexContentCore(RelaxngElement ct, bool isNew) { int position = 0; bool consumed = false; do { switch (source.NodeType) { case XmlNodeType.Element: RelaxngPattern p = GetElementContent(ct); RelaxngGroup g = null; if (p == null) { g = new RelaxngGroup(); } switch (p.PatternType) { case RelaxngPatternType.OneOrMore: case RelaxngPatternType.ZeroOrMore: ProcessLax((RelaxngSingleContentPattern)p); break; case RelaxngPatternType.Optional: g = (RelaxngGroup) ((RelaxngOptional)p) .Patterns [0]; goto default; case RelaxngPatternType.Group: g = (RelaxngGroup)p; goto default; case RelaxngPatternType.Text: case RelaxngPatternType.Data: g = new RelaxngGroup(); g.Patterns.Add(new RelaxngMixed()); goto default; default: if (g == null) { throw Error(p, "Unexpected pattern: " + p.PatternType); } ProcessSequence(ct, g, ref position, ref consumed, isNew); break; } source.MoveToContent(); break; case XmlNodeType.Text: case XmlNodeType.CDATA: case XmlNodeType.SignificantWhitespace: MarkAsMixed(ct); source.ReadString(); source.MoveToContent(); break; case XmlNodeType.EndElement: return; // finished case XmlNodeType.None: throw new NotImplementedException("Internal Error: Should not happen."); } } while (true); }
private RelaxngInterleave GetAttributes(RelaxngElement el) { return(el.Patterns.Count > 0 ? el.Patterns [0] as RelaxngInterleave : null); }
private void InferAttributes(RelaxngElement ct, bool isNew) { RelaxngInterleave attList = null; Hashtable table = null; do { if (source.NamespaceURI == NamespaceXmlns) { continue; } if (table == null) { attList = GetAttributes(ct); table = CollectAttrTable(attList); } QName attrName = new QName( source.LocalName, source.NamespaceURI); RelaxngPattern attr = table [attrName] as RelaxngPattern; if (attr == null) { if (attList == null) { attList = new RelaxngInterleave(); ct.Patterns.Insert(0, attList); } attList.Patterns.Add( InferNewAttribute( attrName, isNew)); } else { table.Remove(attrName); if (attrName.Namespace.Length > 0) { RelaxngDefine ga = GetGlobalAttribute(attrName); InferMergedAttribute( ga.Patterns [0]); } else { InferMergedAttribute(attr); } } } while (source.MoveToNextAttribute()); // mark all attr definitions that did not appear // as optional. if (table != null) { foreach (RelaxngPattern attr in table.Values) { if (attr is RelaxngOptional) { continue; } attList.Patterns.Remove(attr); RelaxngOptional opt = new RelaxngOptional(); opt.Patterns.Add(attr); attList.Patterns.Add(opt); } } }