private RelaxngElement ReadElementPattern() { RelaxngElement el = new RelaxngElement(); FillLocation(el); if (MoveToFirstAttribute()) { do { if (NamespaceURI != String.Empty) { continue; } switch (LocalName) { case "datatypeLibrary": case "name": case "ns": break; default: throw new RelaxngException("Invalid attribute."); } } while (MoveToNextAttribute()); MoveToElement(); } // try to get name from attribute. if (MoveToAttribute("name")) { el.NameClass = resolvedName(XmlConvert.VerifyName(Value.Trim())); } MoveToElement(); Read(); // read nameClass from content. if (el.NameClass == null) { el.NameClass = ReadNameClass(); } // read patterns. this.ReadPatterns(el); expectEnd("element"); if (el.NameClass == null) { throw new RelaxngException("Name class was not specified."); } return(el); }
private RelaxngElement ReadElementPattern () { RelaxngElement el = new RelaxngElement (); FillLocation (el); if (MoveToFirstAttribute ()) { do { if (NamespaceURI != String.Empty) continue; switch (LocalName) { case "datatypeLibrary": case "name": case "ns": break; default: throw new RelaxngException ("Invalid attribute."); } } while (MoveToNextAttribute ()); MoveToElement (); } // try to get name from attribute. if (MoveToAttribute ("name")) el.NameClass = resolvedName (XmlConvert.VerifyName (Value.Trim ())); MoveToElement (); Read (); // read nameClass from content. if (el.NameClass == null) el.NameClass = ReadNameClass (); // read patterns. this.ReadPatterns (el); expectEnd ("element"); if (el.NameClass == null) throw new RelaxngException ("Name class was not specified."); return el; }
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; }
// 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; }
public void WriteElement (RelaxngElement element) { w.Write ("element "); element.NameClass.WriteRnc (this); w.Write (" {"); WritePatterns (element.Patterns, false); w.Write ("}"); }
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)); } }
// 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 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); }
// 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 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 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 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 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 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; }
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); } } }