Example #1
0
        // It returns RelaxngAttribute for local attribute, and
        // RelaxngRef for global attribute.
        private RelaxngPattern InferNewAttribute(
            QName attrName, bool isNewTypeDefinition)
        {
            RelaxngPattern p = null;
            bool           mergedRequired = false;

            if (attrName.Namespace.Length > 0)
            {
                // global attribute; might be already defined.
                // (Actually RELAX NG has no concept of "global
                // attributes" but it is still useful to
                // represent attributes in global scope.
                RelaxngDefine attr = GetGlobalAttribute(
                    attrName);
                if (attr == null)
                {
                    attr = CreateGlobalAttribute(attrName);
                    attr.Patterns.Add(CreateSimplePattern(
                                          InferSimpleType(source.Value)));
                }
                else
                {
                    RelaxngAttribute a = attr.Patterns [0] as RelaxngAttribute;
                    if (a != null)
                    {
                        mergedRequired = true;
                    }
                    else
                    {
                        RelaxngOptional opt =
                            (RelaxngOptional)attr.Patterns [0];
                        a = (RelaxngAttribute)opt.Patterns [0];
                    }
                    InferMergedAttribute(a);
                }
                RelaxngRef r = new RelaxngRef();
                r.Name = attr.Name;
                p      = r;
            }
            else
            {
                // local attribute
                RelaxngAttribute a = new RelaxngAttribute();
                a.NameClass = new RelaxngName(
                    attrName.Name, attrName.Namespace);
                a.Pattern = CreateSimplePattern(
                    InferSimpleType(source.Value));
                p = a;
            }
            // optional
            if (laxOccurence ||
                (!isNewTypeDefinition && !mergedRequired))
            {
                RelaxngOptional opt = new RelaxngOptional();
                opt.Patterns.Add(p);
                p = opt;
            }

            return(p);
        }
Example #2
0
        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());
            }
        }
Example #3
0
        private void Run()
        {
            // move to top-level element
            source.MoveToContent();
            int depth = source.Depth;

            if (source.NodeType != XmlNodeType.Element)
            {
                throw new ArgumentException("Argument XmlReader content is expected to be an element.");
            }

            QName qname = new QName(source.LocalName,
                                    source.NamespaceURI);
            RelaxngDefine el = GetGlobalElement(qname);

            if (el == null)
            {
                el = CreateGlobalElement(qname);
                InferElement(el, true);
            }
            else
            {
                InferElement(el, false);
            }
            RelaxngStart start = new RelaxngStart();

            start.Combine = "choice";
            RelaxngRef topRef = new RelaxngRef();

            topRef.Name   = el.Name;
            start.Pattern = topRef;
            grammar.Starts.Add(start);
        }
Example #4
0
 // Note that it might not be used directly when a grammar
 // contains more than one "define" for an identical name
 // (compact syntax does not support "combine" attribute).
 public void WriteDefine(RelaxngDefine define)
 {
     if (IsKeyword(define.Name))
     {
         w.Write('\\');
     }
     w.Write(define.Name);
     if (define.Combine == null)
     {
         w.Write(" = ");
     }
     else
     {
         w.Write(define.Combine.Trim() == "interleave" ?
                 " &= " : " |= ");
     }
     if (define.Patterns.Count == 0)
     {
         w.Write("empty");
     }
     else
     {
         define.Patterns [0].WriteRnc(this);
         for (int i = 1; i < define.Patterns.Count; i++)
         {
             w.Write(",");
             define.Patterns [i].WriteRnc(this);
         }
     }
     w.WriteLine();
     w.WriteLine();
 }
Example #5
0
        private bool ElementMatches(RelaxngRef el)
        {
            RelaxngDefine def = elements [new QName(
                                              source.LocalName, source.NamespaceURI)]
                                as RelaxngDefine;

            return(def != null && def.Name == el.Name);
        }
Example #6
0
        RelaxngDefine DefineElement(XmlSchemaElement el)
        {
            RelaxngDefine def = new RelaxngDefine();

            def.Patterns.Add(CreateElement(el));
            def.Name = el.Name;

            return(def);
        }
Example #7
0
        private RelaxngDefine CreateGlobalAttribute(QName name)
        {
            RelaxngDefine def = new RelaxngDefine();

            def.Name = CreateUniqueName(name.Name + "-attr");
            RelaxngAttribute attr = new RelaxngAttribute();

            attr.NameClass = new RelaxngName(
                name.Name, name.Namespace);
            def.Patterns.Add(attr);
            attributes.Add(name, def);
            grammar.Defines.Add(def);
            return(def);
        }
Example #8
0
        // 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);
        }
Example #9
0
        // validate string value agains attr and
        // if invalid, then relax the type.
        private void InferMergedAttribute(RelaxngPattern ap)
        {
            switch (ap.PatternType)
            {
            case RelaxngPatternType.Ref:
                string        refName = ((RelaxngRef)ap).Name;
                RelaxngDefine def     = GetDefine(refName);
                InferMergedAttribute(def.Patterns [0]);
                return;

            case RelaxngPatternType.Optional:
                InferMergedAttribute(
                    ((RelaxngOptional)ap).Patterns [0]);
                return;
            }

            RelaxngAttribute attr = (RelaxngAttribute)ap;

            RelaxngPattern p = attr.Pattern;

            if (p is RelaxngText)
            {
                return;                 // We could do nothing anymore.
            }
            if (p is RelaxngEmpty)
            {
                if (source.Value.Length == 0)
                {
                    return;                     // We can keep empty.
                }
                // We still could infer a choice of empty and
                // data, but it's being too complicated. So
                // here we just set text.
                attr.Pattern = new RelaxngText();
                return;
            }
            RelaxngData data = p as RelaxngData;

            if (data == null)
            {
                throw Error(p, "This inference implementation only allows text, empty and data for an attribute.");
            }
            attr.Pattern = CreateSimplePattern(
                InferMergedType(source.Value,
                                new QName(data.Type, data.DatatypeLibrary)));
        }
Example #10
0
        private void ProcessLax(RelaxngSingleContentPattern scp)
        {
            RelaxngChoice c = (RelaxngChoice)scp.Patterns [0];

            foreach (RelaxngPattern p in c.Patterns)
            {
                RelaxngRef el = p as RelaxngRef;
                if (el == null)
                {
                    RelaxngOneOrMore oom =
                        (RelaxngOneOrMore)p;
                    el = (RelaxngRef)oom.Patterns [0];
                }
                if (el == null)
                {
                    throw Error(c, String.Format("Target pattern contains unacceptable child pattern {0}. Only ref is allowed here."));
                }
                if (ElementMatches(el))
                {
                    InferElement(el, false);
                    return;
                }
            }
            // append a new element particle to lax term.
            QName qname = new QName(
                source.LocalName, source.NamespaceURI);
            RelaxngDefine def = GetGlobalElement(qname);

            if (def == null)
            {
                def = CreateGlobalElement(qname);                  // used to be CreateElement().
                InferElement(def, true);
            }
            else
            {
                InferElement(def, false);
            }
            RelaxngRef nel = new RelaxngRef();

            nel.Name = def.Name;
            c.Patterns.Add(nel);
        }
Example #11
0
        RelaxngGrammar DtdXsd2Rng(XmlSchema xsd, string ns)
        {
            g = new RelaxngGrammar();
            g.DefaultNamespace = ns;
            RelaxngStart start = new RelaxngStart();

            g.Starts.Add(start);
            RelaxngChoice choice = new RelaxngChoice();

            start.Pattern = choice;

            // There are only elements.
            foreach (XmlSchemaElement el in xsd.Items)
            {
                RelaxngDefine def = DefineElement(el);
                g.Defines.Add(def);
                RelaxngRef dref = new RelaxngRef();
                dref.Name = def.Name;
                choice.Patterns.Add(dref);
            }

            return(g);
        }
Example #12
0
        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));
                }
            }
        }
Example #13
0
        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);
                }
            }
        }
Example #14
0
        private void InferElement(RelaxngRef r, bool isNew)
        {
            RelaxngDefine body = GetDefine(r.Name);

            InferElement(body, isNew);
        }