private IRdfXmlEvent GetElement()
        {
            // Generate Element Event
            ElementEvent el = new ElementEvent(_reader.Name, GetBaseUri(), _reader.Value, GetPosition());

            _requireEndElement = _reader.IsEmptyElement;

            // Read Attribute Events
            if (_reader.HasAttributes)
            {
                for (int i = 0; i < _reader.AttributeCount; i++)
                {
                    IRdfXmlEvent attr = GetNextAttribute();
                    if (attr is AttributeEvent)
                    {
                        el.Attributes.Add((AttributeEvent)attr);
                    }
                    else if (attr is NamespaceAttributeEvent)
                    {
                        el.NamespaceAttributes.Add((NamespaceAttributeEvent)attr);
                    }
                    else if (attr is LanguageAttributeEvent)
                    {
                        el.Language = ((LanguageAttributeEvent)attr).Language;
                    }
                    else if (attr is ParseTypeAttributeEvent)
                    {
                        el.ParseType = ((ParseTypeAttributeEvent)attr).ParseType;
                        el.Attributes.Add(new AttributeEvent(_reader.Name, _reader.Value, _reader.Value, GetPosition()));
                    }
                    else if (attr is XmlBaseAttributeEvent)
                    {
                        el.BaseUri      = ((XmlBaseAttributeEvent)attr).BaseUri;
                        _currentBaseUri = el.BaseUri;
                    }
                }
            }

            // Validate generated Attributes for Namespace Confusion and URIRef encoding
            foreach (AttributeEvent a in el.Attributes)
            {
                // Namespace Confusion should only apply to Attributes without a Namespace specified
                if (a.Namespace.Equals(String.Empty))
                {
                    if (RdfXmlSpecsHelper.IsAmbigiousAttributeName(a.LocalName))
                    {
                        // Can't use any of the RDF terms that mandate the rdf: prefix without it
                        throw new RdfParseException("An Attribute with an ambigious name '" + a.LocalName + "' was encountered.  The following attribute names MUST have the rdf: prefix - about, aboutEach, ID, bagID, type, resource, parseType");
                    }
                }

                // URIRef encoding check
                if (!RdfXmlSpecsHelper.IsValidUriRefEncoding(a.Value))
                {
                    throw new RdfParseException("An Attribute with an incorrectly encoded URIRef was encountered, URIRef's must be encoded in Unicode Normal Form C");
                }
            }

            return(el);
        }
示例#2
0
        /// <summary>
        /// Helper function which generates standardised Error Messages
        /// </summary>
        /// <param name="message">Error Message</param>
        /// <param name="production">The Production where the Error occurred</param>
        /// <param name="evt">Event causing the Error</param>
        /// <returns></returns>
        public static RdfParseException Error(String message, String production, IRdfXmlEvent evt)
        {
            StringBuilder output = new StringBuilder();

            if (evt.Position != null)
            {
                output.Append('[');
                output.Append("Line ");
                output.Append(evt.Position.StartLine);
                output.Append(" Column ");
                output.Append(evt.Position.StartPosition);
                output.Append("] ");
            }
            output.AppendLine(message);
            if (!production.Equals(String.Empty))
            {
                output.AppendLine("Occurred in Grammar Production '" + production + "'");
            }
            if (!evt.SourceXml.Equals(String.Empty))
            {
                output.AppendLine("[Source XML]");
                output.AppendLine(evt.SourceXml);
            }

            if (evt.Position != null)
            {
                return(new RdfParseException(output.ToString(), evt.Position));
            }
            else
            {
                return(new RdfParseException(output.ToString()));
            }
        }
示例#3
0
        /// <summary>
        /// Helper function which generates standardised Error Messages
        /// </summary>
        /// <param name="message">Error Message</param>
        /// <param name="production">The Production where the Error occurred</param>
        /// <param name="evt">Event causing the Error</param>
        /// <returns></returns>
        public static RdfParseException Error(String message, String production, IRdfXmlEvent evt)
        {
            StringBuilder output = new StringBuilder();
            if (evt.Position != null)
            {
                output.Append('[');
                output.Append("Line ");
                output.Append(evt.Position.StartLine);
                output.Append(" Column ");
                output.Append(evt.Position.StartPosition);
                output.Append("] ");
            }
            output.AppendLine(message);
            if (!production.Equals(String.Empty)) output.AppendLine("Occurred in Grammar Production '" + production + "'");
            if (!evt.SourceXml.Equals(String.Empty))
            {
                output.AppendLine("[Source XML]");
                output.AppendLine(evt.SourceXml);
            }

            if (evt.Position != null)
            {
                return new RdfParseException(output.ToString(), evt.Position);
            }
            else
            {
                return new RdfParseException(output.ToString());
            }
        }
示例#4
0
 /// <summary>
 /// Helper function which generates standardised Error Messages
 /// </summary>
 /// <param name="message">Error Message</param>
 /// <param name="evt">Event causing the Error</param>
 /// <returns></returns>
 public static RdfParseException Error(String message, IRdfXmlEvent evt)
 {
     return(Error(message, String.Empty, evt));
 }
示例#5
0
        /// <summary>
        /// Implementation of the RDF/XML Grammar Production 'parseTypeCollectionPropertyElt'
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="eventlist">Queue of Events that make up the Collection Parse Type Property Element and its Children</param>
        /// <param name="parent">Parent Event (ie. Node) of the Property Element</param>
        private void GrammarProductionParseTypeCollectionPropertyElement(RdfXmlParserContext context, IEventQueue<IRdfXmlEvent> eventlist, IRdfXmlEvent parent)
        {
            //Tracing
            if (this._traceparsing)
            {
                this.ProductionTracePartial("Parse Type Collection Property Element");
            }

            //Get the first Event, should be an ElementEvent
            //Type checking is done by the Parent Production
            IRdfXmlEvent first = eventlist.Dequeue();
            ElementEvent element = (ElementEvent)first;
            if (this._traceparsing) this.ProductionTracePartial(element);

            //Apply Namespaces
            this.ApplyNamespaces(context, element);

            //Validate Attributes
            String ID = String.Empty;
            if (element.Attributes.Count > 2)
            {
                //Can't be more than 2 Attributes, only allowed an optional rdf:ID and a required rdf:parseType
                throw ParserHelper.Error("An Property Element with Parse Type 'Collection' was encountered with too many Attributes.  Only rdf:ID and rdf:parseType are allowed on Property Elements with Parse Type 'Collection'", "Parse Type Collection Property Element", element);
            }
            else
            {
                //Check the attributes that do exist
                foreach (AttributeEvent a in element.Attributes)
                {
                    if (RdfXmlSpecsHelper.IsIDAttribute(a))
                    {
                        ID = "#" + a.Value;
                    }
                    else if (a.QName.Equals("rdf:parseType"))
                    {
                        //OK
                    }
                    else
                    {
                        //Invalid Attribute
                        throw ParserHelper.Error("Unexpected Attribute '" + a.QName + "' was encountered on a Property Element with Parse Type 'Collection'.  Only rdf:ID and rdf:parseType are allowed on Property Elements with Parse Type 'Collection'", "Parse Type Collection Property Element", element);
                    }
                }
            }

            //Build sequence of Blank Nodes
            IRdfXmlEvent next;
            IRdfXmlEvent nodeElement;

            Queue<ElementEvent> seqNodes = new Queue<ElementEvent>();
            while (eventlist.Count > 1)
            {
                #region Node Element Processing
                //Need to process the Node Element first

                //Create a new Sublist
                IEventQueue<IRdfXmlEvent> subevents = new EventQueue<IRdfXmlEvent>();
                int nesting = 0;
                nodeElement = eventlist.Peek();

                //Add Node Element to sequence
                seqNodes.Enqueue((ElementEvent)nodeElement);

                //Gather the Sublist taking account of nesting
                do
                {
                    next = eventlist.Dequeue();
                    subevents.Enqueue(next);

                    if (next is ElementEvent)
                    {
                        nesting++;
                    }
                    else if (next is EndElementEvent)
                    {
                        nesting--;
                    }
                } while (nesting > 0);

                //Call the next Grammar Production
                this.GrammarProductionNodeElement(context, subevents);

                #endregion
            }

            //Build a triple expressing the start of the list (which may be an empty list)
            INode subj, pred, obj;
            INode firstPred, restPred;
            INode b1, b2;

            //Subject comes from Parent
            ElementEvent parentElement = (ElementEvent)parent;
            subj = parentElement.SubjectNode;

            //Validate the ID (if any)
            if (!ID.Equals(String.Empty))
            {
                this.ValidateID(context, ID.Substring(1), subj);
            }

            //Predicate from the Element
            pred = this.Resolve(context, element);//context.Handler.CreateUriNode(element.QName);

            if (seqNodes.Count > 0)
            {
                //Non-empty list
                ElementEvent node;

                //Get first Element from the Queue
                node = seqNodes.Dequeue();

                //Object is first thing in the Sequence which we create a Blank Node for
                b1 = context.Handler.CreateBlankNode();

                //Assert
                if (!context.Handler.HandleTriple(new Triple(subj, pred, b1))) ParserHelper.Stop();

                //Reify if applicable
                if (!ID.Equals(String.Empty))
                {
                    //Resolve the Uri
                    UriReferenceEvent uriref = new UriReferenceEvent(ID, String.Empty);
                    IUriNode uri = this.Resolve(context, uriref, element.BaseUri);

                    this.Reify(context, uri, subj, pred, b1);
                }

                //Set the first element in the list
                subj = b1;
                firstPred = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListFirst));
                if (!context.Handler.HandleTriple(new Triple(subj, firstPred, node.SubjectNode))) ParserHelper.Stop();

                //Middle elements of the list
                restPred = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListRest));
                while (seqNodes.Count >= 1)
                {
                    node = seqNodes.Dequeue();

                    //Set Node 2 to be the rest of the previous items list
                    b2 = context.Handler.CreateBlankNode();
                    if (!context.Handler.HandleTriple(new Triple(b1, restPred, b2))) ParserHelper.Stop();

                    //Set Node 2 to be the start of it's own list
                    if (!context.Handler.HandleTriple(new Triple(b2, firstPred, node.SubjectNode))) ParserHelper.Stop();

                    b1 = b2;
                }

                //Set last element of the list to have its rest as nil
                if (!context.Handler.HandleTriple(new Triple(b1, restPred, context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil))))) ParserHelper.Stop();
            }
            else
            {
                //Empty list

                //Object is therefore rdf:nil
                obj = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil));

                //Assert
                if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop();

                //Reify if applicable
                if (!ID.Equals(String.Empty))
                {
                    //Resolve the Uri
                    UriReferenceEvent uriref = new UriReferenceEvent(ID, String.Empty);
                    IUriNode uri = this.Resolve(context, uriref, element.BaseUri);

                    this.Reify(context, uri, subj, pred, obj);
                }
            }

            //Check last event is an EndElementEvent
            next = eventlist.Dequeue();
            if (!(next is EndElementEvent))
            {
                throw ParserHelper.Error("Unexpected Event '" + next.GetType().ToString() + "', expected an EndElementEvent to terminate a Parse Type Collection Property Element!", "Parse Type Collection Property Element", next);
            }
        }
示例#6
0
        /// <summary>
        /// Implementation of the RDF/XML Grammar Production 'literalPropertyElt'
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="eventlist">Queue of Events that make up the Literal Property Element and its Children</param>
        /// <param name="parent">Parent Event (ie. Node) of the Property Element</param>
        private void GrammarProductionLiteralPropertyElement(RdfXmlParserContext context, IEventQueue<IRdfXmlEvent> eventlist, IRdfXmlEvent parent)
        {
            //Tracing
            if (this._traceparsing)
            {
                this.ProductionTracePartial("Literal Property Element");
            }

            //Get the 3 Events (should only be three)
            IRdfXmlEvent first, middle, last;
            first = eventlist.Dequeue();
            middle = eventlist.Dequeue();
            last = eventlist.Dequeue();

            //If Queue is non-empty then Error
            if (eventlist.Count > 0)
            {
                throw ParserHelper.Error("Too many events encountered while trying to parse a Literal Property Element", first);
            }

            ElementEvent element = (ElementEvent)first;
            if (this._traceparsing) this.ProductionTracePartial(element);

            //Apply Namespaces
            this.ApplyNamespaces(context, element);

            //Validate that the middle event is a TextEvent
            if (!(middle is TextEvent))
            {
                throw ParserHelper.Error("Unexpected event '" + middle.GetType().ToString() + "', expected a TextEvent in a Literal Property Element", middle);
            }
            TextEvent text = (TextEvent)middle;

            //Validate the Attributes
            String ID = String.Empty;
            String datatype = String.Empty;
            if (element.Attributes.Count > 2)
            {
                throw ParserHelper.Error("A Literal Property Element contains too many attributes, only rdf:ID and rdf:datatype are permitted", element);
            }
            else
            {
                //Only rdf:ID and rdf:datatype allowed
                foreach (AttributeEvent a in element.Attributes)
                {
                    if (RdfXmlSpecsHelper.IsIDAttribute(a)) {
                        ID = "#" + a.Value;
                    }
                    else if (RdfXmlSpecsHelper.IsDataTypeAttribute(a))
                    {
                        datatype = a.Value;
                    }
                    else
                    {
                        throw ParserHelper.Error("A Literal Property Element contains an unexpected attribute, only rdf:ID and rdf:datatype are permitted", element);
                    }
                }
            }

            //Create the Nodes for the Graph
            INode subj, pred, obj;

            //Get the Subject from the Parent
            ElementEvent parentEl = (ElementEvent)parent;
            subj = parentEl.SubjectNode;

            //Validate the ID (if any)
            if (!ID.Equals(String.Empty))
            {
                this.ValidateID(context, ID.Substring(1), subj);
            }

            //Create a Predicate from this Element
            pred = this.Resolve(context, element);//context.Handler.CreateUriNode(element.QName);

            //Create an Object from the Text Event
            if (datatype.Equals(String.Empty))
            {
                //No Type with possible Language
                if (element.Language.Equals(String.Empty))
                {
                    obj = context.Handler.CreateLiteralNode(text.Value);
                }
                else
                {
                    obj = context.Handler.CreateLiteralNode(text.Value, element.Language);
                }
            }
            else
            {
                //Typed

                //Resolve the Datatype Uri
                UriReferenceEvent dtref = new UriReferenceEvent(datatype, String.Empty);
                IUriNode dturi = this.Resolve(context, dtref, element.BaseUri);

                obj = context.Handler.CreateLiteralNode(text.Value, dturi.Uri);
            }

            //Assert the Triple
            if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop();

            //Reify if applicable
            if (!ID.Equals(String.Empty))
            {
                //Resolve the Uri
                UriReferenceEvent uriref = new UriReferenceEvent(ID, String.Empty);
                IUriNode uri = this.Resolve(context, uriref,element.BaseUri);

                this.Reify(context, uri, subj, pred, obj);
            }
        }
示例#7
0
 /// <summary>
 /// Adds an event to the Queue
 /// </summary>
 /// <param name="e">Event</param>
 public override void Enqueue(IRdfXmlEvent e)
 {
     if (e != null)
     {
         if (e is ClearQueueEvent)
         {
             this.Clear();
         }
         else
         {
             base.Enqueue(e);
         }
     }
 }
示例#8
0
        /// <summary>
        /// Gets the next event from the XML stream
        /// </summary>
        /// <returns></returns>
        public IRdfXmlEvent GetNextEvent()
        {
            if (this._stop) return null;

            //If the Root Element is filled then return it
            if (this._rootEl != null)
            {
                IRdfXmlEvent temp = this._rootEl;
                this._rootEl = null;
                return temp;
            }

            //If Literal Parsing flag is set then we've just read an element which had rdf:parseType="Literal"
            if (this._parseLiteral)
            {
                this._requireEndElement = true;
                this._parseLiteral = false;
                this._noRead = true;
                this._reader.MoveToContent();
                String data = this._reader.ReadInnerXml();
                return new TypedLiteralEvent(data, RdfSpecsHelper.RdfXmlLiteral, data, this.GetPosition());
            }

            //If we need to return an end element then do so
            if (this._requireEndElement)
            {
                this._requireEndElement = false;
                this._currentBaseUri = this._baseUris.Pop();
                return new EndElementEvent(this.GetPosition());
            }

            //If at EOF throw an error
            if (this._reader.EOF) throw new RdfParseException("Unable to read further events as the end of the stream has already been reached");

            //Otherwise attempt to read the next node
            bool read = true;
            if (!this._noRead)
            {
                read = this._reader.Read();
            }
            else
            {
                this._noRead = false;
            }
            if (read)
            {
                //Return the appropriate event for the Node Type
                switch (this._reader.NodeType)
                {
                    case XmlNodeType.Element:
                        //Element
                        if (this._first)
                        {
                            this._first = false;
                            this._rdfRootSeen = this.IsName("RDF", NamespaceMapper.RDF);
                            this._rootEl = this.GetElement();
                            RootEvent root = new RootEvent(this.GetBaseUri(), this._reader.Value, this.GetPosition());
                            root.DocumentElement = (ElementEvent)this._rootEl;
                            root.Children.Add((ElementEvent)this._rootEl);
                            return root;
                        }
                        else
                        {
                            if (!this._first && this.IsName("RDF", NamespaceMapper.RDF))
                            {
                                if (this._rdfRootSeen) throw new RdfParseException("Unexpected nested rdf:RDF node encountered, this is not valid RDF/XML syntax");
                                this._noRead = true;
                                this._first = true;
                                return new ClearQueueEvent();
                            }
                            return this.GetElement();
                        }

                    case XmlNodeType.EndElement:
                        //End of an Element
                        this._currentBaseUri = this._baseUris.Pop();
                        if (this.IsName("RDF", NamespaceMapper.RDF))
                        {
                            this._stop = true;
                        }
                        return new EndElementEvent(this.GetPosition());

                    case XmlNodeType.Attribute:
                        //Attribute
                        throw new RdfParseException("Unexpected Attribute Node encountered");

                    case XmlNodeType.Text:
                        return new TextEvent(this._reader.Value, this._reader.Value, this.GetPosition());

                    case XmlNodeType.CDATA:
                        return new TextEvent(this._reader.Value, this._reader.Value, this.GetPosition());

                    case XmlNodeType.Document:
                    case XmlNodeType.DocumentType:
                    case XmlNodeType.XmlDeclaration:
                    case XmlNodeType.Comment:
                    case XmlNodeType.ProcessingInstruction:
                    case XmlNodeType.Notation:
                    case XmlNodeType.Whitespace:
                        //Node Types that don't generate events and just indicate to continue reading
                        return this.GetNextEvent();

                    default:
                        throw new RdfParseException("Unexpected XML Node Type " + this._reader.NodeType.ToString() + " encountered");
                }
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// Takes the Event Tree and Flattens it into a Queue as per the rules laid out in the RDF/XML Specification
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="evt">Event which is the Root of the Tree (not necessarily a RootEvent)</param>
        /// <param name="nesting">A numeric value used for Parser Tracing to indicate nesting levels of the Event Tree</param>
        private void FlattenEventTree(RdfXmlParserContext context, IRdfXmlEvent evt, int nesting)
        {
            //Add to Queue
            context.Events.Enqueue(evt);

            if (context.TraceParsing)
            {
                Console.Write(nesting + " " + evt.GetType().ToString());
            }

            //Iterate over Children where present
            if (evt is RootEvent)
            {
                RootEvent root = (RootEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine("");
                }
                foreach (IRdfXmlEvent childEvent in root.Children)
                {
                    this.FlattenEventTree(context, childEvent, nesting + 1);
                }

                //No End after a RootEvent
                return;
            }
            else if (evt is ElementEvent)
            {
                ElementEvent element = (ElementEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine(" " + element.Namespace + ":" + element.LocalName);
                }
                if (element.Children.Count > 0)
                {
                    foreach (IRdfXmlEvent childEvent in element.Children)
                    {
                        this.FlattenEventTree(context, childEvent, nesting + 1);
                    }
                }
            }
            else if (evt is TextEvent)
            {
                TextEvent text = (TextEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine(" " + text.Value);
                }

                //No additional End after a Text Event
                return;
            }
            else if (evt is TypedLiteralEvent)
            {
                TypedLiteralEvent tlit = (TypedLiteralEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine();
                }

                //No additional End after a Text Event
                return;
            }

            //Add an End Element Event to the Queue
            EndElementEvent end = new EndElementEvent();
            context.Events.Enqueue(end);
            if (context.TraceParsing)
            {
                String endDescrip = String.Empty;
                if (evt is ElementEvent)
                {
                    ElementEvent temp = (ElementEvent)evt;
                    endDescrip = " " + temp.QName;
                }
                Console.WriteLine(nesting + " " + end.GetType().ToString() + endDescrip);
            }
        }
示例#10
0
        /// <summary>
        /// Implementation of the RDF/XML Grammar Production 'propertyEltList'
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="eventlist">Queue of Events to apply the Production to</param>
        /// <param name="parent">Parent Event (ie. Node) of the Property Elements</param>
        private void GrammarProductionPropertyElementList(RdfXmlParserContext context, IEventQueue<IRdfXmlEvent> eventlist, IRdfXmlEvent parent)
        {
            //Tracing
            if (this._traceparsing)
            {
                this.ProductionTrace("Property Element List");
            }

            IRdfXmlEvent next;

            //Want to break up into a number of sublists
            while (eventlist.Count > 0)
            {
                //Create a new Sublist
                IEventQueue<IRdfXmlEvent> subevents = new EventQueue<IRdfXmlEvent>();
                int nesting = 0;

                //Gather the Sublist taking account of nesting
                do
                {
                    next = eventlist.Dequeue();
                    subevents.Enqueue(next);

                    if (next is ElementEvent)
                    {
                        nesting++;
                    }
                    else if (next is EndElementEvent)
                    {
                        nesting--;
                    }
                } while (nesting > 0);

                //Call the next Grammar Production
                if (subevents.Count > 0) this.GrammarProductionPropertyElement(context, subevents, parent);
            }
        }
示例#11
0
        /// <summary>
        /// Implementation of the RDF/XML Grammar Production 'propertyElt'
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="eventlist">Queue of Events that make up the Property Element and its Children</param>
        /// <param name="parent">Parent Event (ie. Node) of the Property Element</param>
        private void GrammarProductionPropertyElement(RdfXmlParserContext context, IEventQueue<IRdfXmlEvent> eventlist, IRdfXmlEvent parent)
        {
            //Tracing
            if (this._traceparsing)
            {
                this.ProductionTracePartial("Property Element");
            }

            //Get first thing from the Queue
            IRdfXmlEvent first = eventlist.Dequeue();
            ElementEvent element;

            //Must be an ElementEvent
            if (!(first is ElementEvent))
            {
                //Unexpected Event
                throw ParserHelper.Error("Expected an ElementEvent but encountered a '" + first.GetType().ToString() + "'", "PropertyElement", first);
            }

            //Validate the Uri
            element = (ElementEvent)first;
            if (this._traceparsing) this.ProductionTracePartial(element);
            this.ApplyNamespaces(context, element);
            if (!RdfXmlSpecsHelper.IsPropertyElementURI(element.QName))
            {
                //Invalid Uri
                throw ParserHelper.Error("A Property Element was encountered with an invalid URI '" + element.QName + "'\nCore Syntax Terms, Old Syntax Terms and rdf:Description cannot be used as Property Element URIs", "PropertyElement", element);
            }

            //List Expansion
            if (element.QName.Equals("rdf:li"))
            {
                UriReferenceEvent u = this.ListExpand(parent);
                element.SetUri(u);
            }

            //Need to select what to do based on the Type of Property Element
            IRdfXmlEvent next = eventlist.Peek();

            //This call inserts the first element back at the head of the queue
            //Most of the sub-productions here need this
            //Would ideally use Stacks instead of Queues but Queues make more sense for most of the Parsing
            this.QueueJump(eventlist, first);

            if (element.ParseType == RdfXmlParseType.None)
            {
                //A Resource/Literal Property Element

                if (next is ElementEvent)
                {
                    //Resource
                    this.GrammarProductionResourcePropertyElement(context, eventlist, parent);
                }
                else if (next is TextEvent)
                {
                    //Literal
                    this.GrammarProductionLiteralPropertyElement(context, eventlist, parent);
                }
                else if (next is EndElementEvent)
                {
                    //An Empty Property Element
                    this.GrammarProductionEmptyPropertyElement(context, element, parent);
                }
                else
                {
                    //Error
                    throw ParserHelper.Error("An Element which should be Parsed with the Default Parsing Rules was encountered without a valid subsequent Event - Parser cannot proceed!", "Property Element", element);
                }
            }
            else if (element.ParseType == RdfXmlParseType.Literal)
            {
                //A rdf:parseType="Literal" Property Element

                this.GrammarProductionParseTypeLiteralPropertyElement(context, eventlist, parent);
            }
            else if (element.ParseType == RdfXmlParseType.Collection)
            {
                //A rdf:parseType="Collection" Property Element

                this.GrammarProductionParseTypeCollectionPropertyElement(context, eventlist, parent);
            }
            else if (element.ParseType == RdfXmlParseType.Resource)
            {
                //A rdf:parseType="Resource" Property Element

                this.GrammarProductionParseTypeResourcePropertyElement(context, eventlist, parent);
            }
            else if (next is EndElementEvent)
            {
                //An Empty Property Element
                this.GrammarProductionEmptyPropertyElement(context, element, parent);
            }
            else
            {
                //Error
                throw ParserHelper.Error("An Element without a known Parse Type was encountered Or the Parser was unable to determine what to do based on the subsequent event - Parser cannot proceed!", "Node Element", element);
            }
        }
示例#12
0
        /// <summary>
        /// Implementation of the RDF/XML Grammar Production 'parseTypeResourcePropertyElt'
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="eventlist">Queue of Events that make up the Resource Parse Type Property Element and its Children</param>
        /// <param name="parent">Parent Event (ie. Node) of the Property Element</param>
        private void GrammarProductionParseTypeResourcePropertyElement(RdfXmlParserContext context, IEventQueue<IRdfXmlEvent> eventlist, IRdfXmlEvent parent)
        {
            //Tracing
            if (this._traceparsing)
            {
                this.ProductionTracePartial("Parse Type Resource Property Element");
            }

            //Get the first Event, should be an ElementEvent
            //Type checking is done by the Parent Production
            IRdfXmlEvent first = eventlist.Dequeue();
            ElementEvent element = (ElementEvent)first;
            if (this._traceparsing) this.ProductionTracePartial(element);

            //Apply Namespaces
            this.ApplyNamespaces(context, element);

            //Validate Attributes
            String ID = String.Empty;
            if (element.Attributes.Count > 2)
            {
                //Can't be more than 2 Attributes, only allowed an optional rdf:ID and a required rdf:parseType
                throw ParserHelper.Error("An Property Element with Parse Type 'Resource' was encountered with too many Attributes.  Only rdf:ID and rdf:parseType are allowed on Property Elements with Parse Type 'Resource'", "Parse Type Resource Property Element", element);
            }
            else
            {
                //Check the attributes that do exist
                foreach (AttributeEvent a in element.Attributes)
                {
                    if (RdfXmlSpecsHelper.IsIDAttribute(a))
                    {
                        ID = "#" + a.Value;
                    }
                    else if (a.QName.Equals("rdf:parseType"))
                    {
                        //OK
                    }
                    else
                    {
                        //Invalid Attribute
                        throw ParserHelper.Error("Unexpected Attribute '" + a.QName + "' was encountered on a Property Element with Parse Type 'Resource'.  Only rdf:ID and rdf:parseType are allowed on Property Elements with Parse Type 'Resource'", "Parse Type Resource Property Element", element);
                    }
                }
            }

            //Add a Triple about this
            INode subj, pred, obj;

            //Get the Subject from the Parent
            ElementEvent parentEvent = (ElementEvent)parent;
            subj = parentEvent.SubjectNode;

            //Validate the ID (if any)
            if (!ID.Equals(String.Empty))
            {
                this.ValidateID(context, ID.Substring(1), subj);
            }

            //Create the Predicate from the Element
            pred = this.Resolve(context, element);//context.Handler.CreateUriNode(element.QName);

            //Generate a Blank Node ID for the Object
            obj = context.Handler.CreateBlankNode();

            //Assert
            if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop();

            //Reify if applicable
            if (!ID.Equals(String.Empty))
            {
                //Resolve the Uri
                UriReferenceEvent uriref = new UriReferenceEvent(ID, String.Empty);
                IUriNode uri = this.Resolve(context, uriref,element.BaseUri);

                this.Reify(context, uri, subj, pred, obj);
            }

            //Get the next event in the Queue which should be either an Element Event or a End Element Event
            //Validate this
            IRdfXmlEvent next = eventlist.Dequeue();
            if (next is EndElementEvent)
            {
                //Content is Empty so nothing else to do
            }
            else if (next is ElementEvent)
            {
                //Non-Empty Content so need to build a sequence of new events
                IEventQueue<IRdfXmlEvent> subEvents = new EventQueue<IRdfXmlEvent>();

                //Create an rdf:Description event as the container
                ElementEvent descrip = new ElementEvent("rdf:Description", element.BaseUri, String.Empty);
                descrip.Subject = new BlankNodeIDEvent(String.Empty);
                descrip.SubjectNode = obj;
                subEvents.Enqueue(descrip);

                //Add the current element we were looking at
                subEvents.Enqueue(next);

                //Add rest of events in list (exceot the last)
                while (eventlist.Count > 1)
                {
                    subEvents.Enqueue(eventlist.Dequeue());
                }

                //Terminate with an EndElement Event
                subEvents.Enqueue(new EndElementEvent());

                //Process with Node Element Production
                this.GrammarProductionNodeElement(context, subEvents);

                //Get the last thing in the List
                next = eventlist.Dequeue();
            }
            else
            {
                throw ParserHelper.Error("Unexpected Event '" + next.GetType().ToString() + "', expected an ElementEvent or EndElementEvent after a Parse Type Resource Property Element!", "Parse Type Resource Property Element", next);
            }

            //Check for the last thing being an EndElement Event
            if (!(next is EndElementEvent))
            {
                throw ParserHelper.Error("Unexpected Event '" + next.GetType().ToString() + "', expected an EndElementEvent to terminate a Parse Type Resource Property Element!", "Parse Type Resource Property Element", next);
            }
        }
示例#13
0
        /// <summary>
        /// Implementation of the RDF/XML Grammar Production 'parseTypeLiteralPropertyElt'
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="eventlist">Queue of Events that make up the Literal Parse Type Property Element and its Children</param>
        /// <param name="parent">Parent Event (ie. Node) of the Property Element</param>
        private void GrammarProductionParseTypeLiteralPropertyElement(RdfXmlParserContext context, IEventQueue<IRdfXmlEvent> eventlist, IRdfXmlEvent parent)
        {
            //Tracing
            if (this._traceparsing)
            {
                this.ProductionTracePartial("Parse Type Literal Property Element");
            }

            //Get the first Event, should be an ElementEvent
            //Type checking is done by the Parent Production
            IRdfXmlEvent first = eventlist.Dequeue();
            ElementEvent element = (ElementEvent)first;
            if (this._traceparsing) this.ProductionTracePartial(element);

            //Apply Namespaces
            this.ApplyNamespaces(context, element);

            //Validate Attributes
            String ID = String.Empty;
            if (element.Attributes.Count > 2)
            {
                //Can't be more than 2 Attributes, only allowed an optional rdf:ID and a required rdf:parseType
                throw ParserHelper.Error("An Property Element with Parse Type 'Literal' was encountered with too many Attributes.  Only rdf:ID and rdf:parseType are allowed on Property Elements with Parse Type 'Literal'", "Parse Type Literal Property Element", element);
            }
            else
            {
                //Check the attributes that do exist
                foreach (AttributeEvent a in element.Attributes)
                {
                    if (RdfXmlSpecsHelper.IsIDAttribute(a))
                    {
                        ID = "#" + a.Value;
                    }
                    else if (a.QName.Equals("rdf:parseType"))
                    {
                        //OK
                    }
                    else
                    {
                        //Invalid Attribute
                        throw ParserHelper.Error("Unexpected Attribute '" + a.QName + "' was encountered on a Property Element with Parse Type 'Literal'.  Only rdf:ID and rdf:parseType are allowed on Property Elements with Parse Type 'Literal'", "Parse Type Literal Property Element", element);
                    }
                }
            }

            //Get the next event in the Queue which should be a TypedLiteralEvent
            //Validate this
            IRdfXmlEvent lit = eventlist.Dequeue();
            if (!(lit is TypedLiteralEvent))
            {
                throw ParserHelper.Error("Unexpected Event '" + lit.GetType().ToString() + "', expected a TypedLiteralEvent after a Property Element with Parse Type 'Literal'", "Parse Type Literal Property Element", lit);
            }

            //Get the Subject from the Parent
            INode subj, pred, obj;
            ElementEvent parentEl = (ElementEvent) parent;
            subj = parentEl.SubjectNode;

            //Validate the ID (if any)
            if (!ID.Equals(String.Empty))
            {
                this.ValidateID(context, ID.Substring(1), subj);
            }

            //Create the Predicate from the Element
            pred = this.Resolve(context, element);//context.Handler.CreateUriNode(element.QName);

            //Create the Object from the Typed Literal
            TypedLiteralEvent tlit = (TypedLiteralEvent)lit;
            //At the moment we're just going to ensure that we normalize it to Unicode Normal Form C
            String xmllit = tlit.Value;
            #if !NO_NORM
            xmllit = xmllit.Normalize();
            #endif
            obj = context.Handler.CreateLiteralNode(xmllit, UriFactory.Create(tlit.DataType));

            //Assert the Triple
            if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop();

            //Reify if applicable
            if (!ID.Equals(String.Empty))
            {
                //Resolve the Uri
                UriReferenceEvent uriref = new UriReferenceEvent(ID, String.Empty);
                IUriNode uri = this.Resolve(context, uriref,element.BaseUri);

                this.Reify(context, uri, subj, pred, obj);
            }

            //Check for the last thing being an EndElement Event
            IRdfXmlEvent next = eventlist.Dequeue();
            if (!(next is EndElementEvent))
            {
                throw ParserHelper.Error("Unexpected Event '" + next.GetType().ToString() + "', expected an EndElementEvent to terminate a Parse Type Literal Property Element!", "Parse Type Literal Property Element", next);
            }
        }
        /// <summary>
        /// Takes the Event Tree and Flattens it into a Queue as per the rules laid out in the RDF/XML Specification
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="evt">Event which is the Root of the Tree (not necessarily a RootEvent)</param>
        /// <param name="nesting">A numeric value used for Parser Tracing to indicate nesting levels of the Event Tree</param>
        private void FlattenEventTree(RdfXmlParserContext context, IRdfXmlEvent evt, int nesting)
        {
            // Add to Queue
            context.Events.Enqueue(evt);

            if (context.TraceParsing)
            {
                Console.Write(nesting + " " + evt.GetType().ToString());
            }

            // Iterate over Children where present
            if (evt is RootEvent)
            {
                RootEvent root = (RootEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine("");
                }
                foreach (IRdfXmlEvent childEvent in root.Children)
                {
                    FlattenEventTree(context, childEvent, nesting + 1);
                }

                // No End after a RootEvent
                return;
            }
            else if (evt is ElementEvent)
            {
                ElementEvent element = (ElementEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine(" " + element.Namespace + ":" + element.LocalName);
                }
                if (element.Children.Count > 0)
                {
                    foreach (IRdfXmlEvent childEvent in element.Children)
                    {
                        FlattenEventTree(context, childEvent, nesting + 1);
                    }
                }
            }
            else if (evt is TextEvent)
            {
                TextEvent text = (TextEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine(" " + text.Value);
                }

                // No additional End after a Text Event
                return;
            }
            else if (evt is TypedLiteralEvent)
            {
                TypedLiteralEvent tlit = (TypedLiteralEvent)evt;
                if (context.TraceParsing)
                {
                    Console.WriteLine();
                }

                // No additional End after a Text Event
                return;
            }

            // Add an End Element Event to the Queue
            EndElementEvent end = new EndElementEvent();

            context.Events.Enqueue(end);
            if (context.TraceParsing)
            {
                String endDescrip = String.Empty;
                if (evt is ElementEvent)
                {
                    ElementEvent temp = (ElementEvent)evt;
                    endDescrip = " " + temp.QName;
                }
                Console.WriteLine(nesting + " " + end.GetType().ToString() + endDescrip);
            }
        }
        /// <summary>
        /// Given an XML Node creates the relevant RDF/XML Events for it and recurses as necessary
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="node">The Node to create Event(s) from</param>
        /// <param name="parent">The Parent Node of the given Node</param>
        /// <returns></returns>
        private ElementEvent GenerateEvents(RdfXmlParserContext context, XmlNode node, IRdfXmlEvent parent)
        {
            // Get the Base Uri
            String baseUri = String.Empty;

            if (parent is ElementEvent)
            {
                baseUri = ((ElementEvent)parent).BaseUri;
            }
            // Create an ElementEvent for the Node
            ElementEvent element = new ElementEvent(node.LocalName, node.Prefix, baseUri, node.OuterXml);

            // Set the initial Language from the Parent
            ElementEvent parentEl = (ElementEvent)parent;

            element.Language = parentEl.Language;

            #region Attribute Processing

            // Iterate over Attributes
            bool parseTypeLiteral = false;
            foreach (XmlAttribute attr in node.Attributes)
            {
                // Watch out for special attributes
                if (attr.Name == "xml:lang")
                {
                    // Set Language
                    element.Language = attr.Value;
                }
                else if (attr.Name == "xml:base")
                {
                    // Set Base Uri

                    if (RdfXmlSpecsHelper.IsAbsoluteURI(attr.Value))
                    {
                        // Absolute Uri
                        element.BaseUri = attr.Value;
                    }
                    else if (!element.BaseUri.Equals(String.Empty))
                    {
                        // Relative Uri with a Base Uri to resolve against
                        // element.BaseUri += attr.Value;
                        element.BaseUri = Tools.ResolveUri(attr.Value, element.BaseUri);
                    }
                    else
                    {
                        // Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Base URI since there is no in-scope Base URI");
                    }
                }
                else if (attr.Prefix == "xmlns")
                {
                    // Register a Namespace
                    String uri;
                    if (attr.Value.StartsWith("http://"))
                    {
                        // Absolute Uri
                        uri = attr.Value;
                    }
                    else if (!element.BaseUri.Equals(String.Empty))
                    {
                        // Relative Uri with a Base Uri to resolve against
                        // uri = element.BaseUri + attr.Value;
                        uri = Tools.ResolveUri(attr.Value, element.BaseUri);
                    }
                    else
                    {
                        // Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI");
                    }
                    NamespaceAttributeEvent ns = new NamespaceAttributeEvent(attr.LocalName, uri, attr.OuterXml);
                    element.NamespaceAttributes.Add(ns);
                }
                else if (attr.Prefix == String.Empty && attr.Name == "xmlns")
                {
                    // Register a Default Namespace (Empty Prefix)
                    String uri;

                    if (attr.Value.StartsWith("http://"))
                    {
                        // Absolute Uri
                        uri = attr.Value;
                    }
                    else if (!element.BaseUri.Equals(String.Empty))
                    {
                        // Relative Uri with a Base Uri to resolve against
                        // uri = element.BaseUri + attr.Value;
                        uri = Tools.ResolveUri(attr.Value, element.BaseUri);
                    }
                    else
                    {
                        // Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI");
                    }
                    NamespaceAttributeEvent ns = new NamespaceAttributeEvent(String.Empty, uri, attr.OuterXml);
                    element.NamespaceAttributes.Add(ns);
                }
                else if (attr.Prefix == "xml" || (attr.Prefix == String.Empty && attr.LocalName.StartsWith("xml")))
                {
                    // Ignore other Reserved XML Names
                }
                else if (attr.Name == "rdf:parseType" && attr.Value == "Literal")
                {
                    // Literal Parse Type
                    parseTypeLiteral = true;

                    // Create the Attribute
                    AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml);
                    element.Attributes.Add(attrEvent);

                    // Set ParseType property correctly
                    element.ParseType = RdfXmlParseType.Literal;
                }
                else if (attr.Name == "rdf:parseType")
                {
                    // Some other Parse Type

                    // Create the Attribute
                    AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml);
                    element.Attributes.Add(attrEvent);

                    // Set the ParseType property correctly
                    if (attr.Value == "Resource")
                    {
                        element.ParseType = RdfXmlParseType.Resource;
                    }
                    else if (attr.Value == "Collection")
                    {
                        element.ParseType = RdfXmlParseType.Collection;
                    }
                    else
                    {
                        // Have to assume Literal
                        element.ParseType = RdfXmlParseType.Literal;
                        parseTypeLiteral  = true;

                        // Replace the Parse Type attribute with one saying it is Literal
                        element.Attributes.Remove(attrEvent);
                        attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, "Literal", attr.OuterXml);
                    }
                }
                else
                {
                    // Normal Attribute which we generate an Event from
                    AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml);
                    element.Attributes.Add(attrEvent);
                }
            }

            // Validate generated Attributes for Namespace Confusion and URIRef encoding
            foreach (AttributeEvent a in element.Attributes)
            {
                // Namespace Confusion should only apply to Attributes without a Namespace specified
                if (a.Namespace.Equals(String.Empty))
                {
                    if (RdfXmlSpecsHelper.IsAmbigiousAttributeName(a.LocalName))
                    {
                        // Can't use any of the RDF terms that mandate the rdf: prefix without it
                        throw ParserHelper.Error("An Attribute with an ambigious name '" + a.LocalName + "' was encountered.  The following attribute names MUST have the rdf: prefix - about, aboutEach, ID, bagID, type, resource, parseType", element);
                    }
                }

                // URIRef encoding check
                if (!RdfXmlSpecsHelper.IsValidUriRefEncoding(a.Value))
                {
                    throw ParserHelper.Error("An Attribute with an incorrectly encoded URIRef was encountered, URIRef's must be encoded in Unicode Normal Form C", a);
                }
            }

            #endregion

            // Don't proceed if Literal Parse Type is on
            if (parseTypeLiteral)
            {
                // Generate an XMLLiteral from its Inner Xml (if any)
                TypedLiteralEvent lit = new TypedLiteralEvent(node.InnerXml.Normalize(), RdfSpecsHelper.RdfXmlLiteral, node.InnerXml);
                element.Children.Add(lit);
                return(element);
            }

            // Are there Child Nodes?
            if (node.HasChildNodes)
            {
                // Take different actions depending on the Number and Type of Child Nodes
                if (node.ChildNodes.Count > 1)
                {
                    // Multiple Child Nodes

                    // Iterate over Child Nodes
                    foreach (XmlNode child in node.ChildNodes)
                    {
                        // Ignore Irrelevant Node Types
                        if (IsIgnorableNode(child))
                        {
                            continue;
                        }

                        // Generate an Event for the Child Node
                        ElementEvent childEvent = GenerateEvents(context, child, element);
                        element.Children.Add(childEvent);
                    }
                }
                else if (node.ChildNodes[0].NodeType == XmlNodeType.Text)
                {
                    // Single Child which is a Text Node

                    // Generate a Text Event
                    TextEvent text = new TextEvent(node.InnerText.Normalize(), node.OuterXml);
                    element.Children.Add(text);
                }
                else if (node.ChildNodes[0].NodeType == XmlNodeType.CDATA)
                {
                    // Single Child which is a CData Node

                    TextEvent text = new TextEvent(node.InnerXml.Normalize(), node.OuterXml);
                    element.Children.Add(text);
                }
                else
                {
                    // Single Child which is not a Text Node

                    // Recurse on the single Child Node
                    if (!IsIgnorableNode(node.ChildNodes[0]))
                    {
                        ElementEvent childEvent = GenerateEvents(context, node.ChildNodes[0], element);
                        element.Children.Add(childEvent);
                    }
                }
            }

            return(element);
        }
示例#16
0
 /// <summary>
 /// Adds an event to the end of the Queue
 /// </summary>
 /// <param name="e">Event</param>
 public override void Enqueue(IRdfXmlEvent e)
 {
     this._events.Enqueue(e);
 }
        /// <summary>
        /// Given an XML Node creates the relevant RDF/XML Events for it and recurses as necessary
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="node">The Node to create Event(s) from</param>
        /// <param name="parent">The Parent Node of the given Node</param>
        /// <returns></returns>
        private ElementEvent GenerateEvents(RdfXmlParserContext context, XmlNode node, IRdfXmlEvent parent)
        {
            //Get the Base Uri
            String baseUri = String.Empty;
            if (parent is ElementEvent)
            {
                baseUri = ((ElementEvent)parent).BaseUri;
            }
            //Create an ElementEvent for the Node
            ElementEvent element = new ElementEvent(node.LocalName, node.Prefix, baseUri, node.OuterXml);

            //Set the initial Language from the Parent
            ElementEvent parentEl = (ElementEvent)parent;
            element.Language = parentEl.Language;

            #region Attribute Processing

            //Iterate over Attributes
            bool parseTypeLiteral = false;
            foreach (XmlAttribute attr in node.Attributes)
            {
                //Watch out for special attributes
                if (attr.Name == "xml:lang")
                {
                    //Set Language
                    element.Language = attr.Value;
                }
                else if (attr.Name == "xml:base")
                {
                    //Set Base Uri

                    if (RdfXmlSpecsHelper.IsAbsoluteURI(attr.Value))
                    {
                        //Absolute Uri
                        element.BaseUri = attr.Value;
                    }
                    else if (!element.BaseUri.Equals(String.Empty))
                    {
                        //Relative Uri with a Base Uri to resolve against
                        //element.BaseUri += attr.Value;
                        element.BaseUri = Tools.ResolveUri(attr.Value, element.BaseUri);
                    }
                    else
                    {
                        //Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Base URI since there is no in-scope Base URI");
                    }
                }
                else if (attr.Prefix == "xmlns")
                {
                    //Register a Namespace
                    String uri;
                    if (attr.Value.StartsWith("http://"))
                    {
                        //Absolute Uri
                        uri = attr.Value;
                    }
                    else if (!element.BaseUri.Equals(String.Empty))
                    {
                        //Relative Uri with a Base Uri to resolve against
                        //uri = element.BaseUri + attr.Value;
                        uri = Tools.ResolveUri(attr.Value, element.BaseUri);
                    }
                    else
                    {
                        //Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI");
                    }
                    NamespaceAttributeEvent ns = new NamespaceAttributeEvent(attr.LocalName, uri, attr.OuterXml);
                    element.NamespaceAttributes.Add(ns);
                }
                else if (attr.Prefix == String.Empty && attr.Name == "xmlns")
                {
                    //Register a Default Namespace (Empty Prefix)
                    String uri;

                    if (attr.Value.StartsWith("http://"))
                    {
                        //Absolute Uri
                        uri = attr.Value;
                    }
                    else if (!element.BaseUri.Equals(String.Empty))
                    {
                        //Relative Uri with a Base Uri to resolve against
                        //uri = element.BaseUri + attr.Value;
                        uri = Tools.ResolveUri(attr.Value, element.BaseUri);
                    }
                    else
                    {
                        //Relative Uri with no Base Uri
                        throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI");
                    }
                    NamespaceAttributeEvent ns = new NamespaceAttributeEvent(String.Empty, uri, attr.OuterXml);
                    element.NamespaceAttributes.Add(ns);
                }
                else if (attr.Prefix == "xml" || (attr.Prefix == String.Empty && attr.LocalName.StartsWith("xml")))
                {
                    //Ignore other Reserved XML Names
                }
                else if (attr.Name == "rdf:parseType" && attr.Value == "Literal")
                {
                    //Literal Parse Type
                    parseTypeLiteral = true;

                    //Create the Attribute
                    AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml);
                    element.Attributes.Add(attrEvent);

                    //Set ParseType property correctly
                    element.ParseType = RdfXmlParseType.Literal;
                }
                else if (attr.Name == "rdf:parseType")
                {
                    //Some other Parse Type

                    //Create the Attribute
                    AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml);
                    element.Attributes.Add(attrEvent);

                    //Set the ParseType property correctly
                    if (attr.Value == "Resource")
                    {
                        element.ParseType = RdfXmlParseType.Resource;
                    }
                    else if (attr.Value == "Collection")
                    {
                        element.ParseType = RdfXmlParseType.Collection;
                    }
                    else
                    {
                        //Have to assume Literal
                        element.ParseType = RdfXmlParseType.Literal;
                        parseTypeLiteral = true;

                        //Replace the Parse Type attribute with one saying it is Literal
                        element.Attributes.Remove(attrEvent);
                        attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, "Literal", attr.OuterXml);
                    }
                }
                else
                {
                    //Normal Attribute which we generate an Event from
                    AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml);
                    element.Attributes.Add(attrEvent);
                }
            }

            //Validate generated Attributes for Namespace Confusion and URIRef encoding
            foreach (AttributeEvent a in element.Attributes)
            {
                //Namespace Confusion should only apply to Attributes without a Namespace specified
                if (a.Namespace.Equals(String.Empty))
                {
                    if (RdfXmlSpecsHelper.IsAmbigiousAttributeName(a.LocalName))
                    {
                        //Can't use any of the RDF terms that mandate the rdf: prefix without it
                        throw ParserHelper.Error("An Attribute with an ambigious name '" + a.LocalName + "' was encountered.  The following attribute names MUST have the rdf: prefix - about, aboutEach, ID, bagID, type, resource, parseType", element);
                    }
                }

                //URIRef encoding check
                if (!RdfXmlSpecsHelper.IsValidUriRefEncoding(a.Value))
                {
                    throw ParserHelper.Error("An Attribute with an incorrectly encoded URIRef was encountered, URIRef's must be encoded in Unicode Normal Form C", a);
                }
            }

            #endregion

            //Don't proceed if Literal Parse Type is on
            if (parseTypeLiteral)
            {
                //Generate an XMLLiteral from its Inner Xml (if any)
                TypedLiteralEvent lit = new TypedLiteralEvent(node.InnerXml.Normalize(), RdfSpecsHelper.RdfXmlLiteral, node.InnerXml);
                element.Children.Add(lit);
                return element;
            }

            //Are there Child Nodes?
            if (node.HasChildNodes)
            {
                //Take different actions depending on the Number and Type of Child Nodes
                if (node.ChildNodes.Count > 1)
                {
                    //Multiple Child Nodes

                    //Iterate over Child Nodes
                    foreach (XmlNode child in node.ChildNodes)
                    {
                        //Ignore Irrelevant Node Types
                        if (this.IsIgnorableNode(child))
                        {
                            continue;
                        }

                        //Generate an Event for the Child Node
                        ElementEvent childEvent = this.GenerateEvents(context, child, element);
                        element.Children.Add(childEvent);
                    }
                }
                else if (node.ChildNodes[0].NodeType == XmlNodeType.Text)
                {
                    //Single Child which is a Text Node

                    //Generate a Text Event
                    TextEvent text = new TextEvent(node.InnerText.Normalize(), node.OuterXml);
                    element.Children.Add(text);
                }
                else if (node.ChildNodes[0].NodeType == XmlNodeType.CDATA)
                {
                    //Single Child which is a CData Node

                    TextEvent text = new TextEvent(node.InnerXml.Normalize(), node.OuterXml);
                    element.Children.Add(text);
                }
                else
                {
                    //Single Child which is not a Text Node

                    //Recurse on the single Child Node
                    if (!this.IsIgnorableNode(node.ChildNodes[0]))
                    {
                        ElementEvent childEvent = this.GenerateEvents(context, node.ChildNodes[0], element);
                        element.Children.Add(childEvent);
                    }
                }
            }

            return element;
        }
示例#18
0
        /// <summary>
        /// Implementation of the RDF/XML Grammar Production 'resourcePropertyElt'
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="eventlist">Queue of Events that make up the Resource Property Element and its Children</param>
        /// <param name="parent">Parent Event (ie. Node) of the Property Element</param>
        private void GrammarProductionResourcePropertyElement(RdfXmlParserContext context, IEventQueue<IRdfXmlEvent> eventlist, IRdfXmlEvent parent)
        {
            //Tracing
            if (this._traceparsing)
            {
                this.ProductionTracePartial("Resource Property Element");
            }

            //Cast to an ElementEvent
            //We don't validate type here since we know this will be an ElementEvent because the calling function
            //will have done this validation previously
            IRdfXmlEvent first = eventlist.Dequeue();
            IRdfXmlEvent next = eventlist.Peek();
            ElementEvent element = (ElementEvent)first;
            if (this._traceparsing) this.ProductionTracePartial(element);

            //Apply Namespaces
            this.ApplyNamespaces(context, element);

            //Only allowed one attribute max which must be an ID attribute
            String ID = String.Empty;
            if (element.Attributes.Count > 1)
            {
                throw ParserHelper.Error("A Resource Property Element contains too many Attributes, only rdf:ID is permitted", element);
            }
            else if (element.Attributes.Count == 1)
            {
                if (!RdfXmlSpecsHelper.IsIDAttribute(element.Attributes.First()))
                {
                    throw ParserHelper.Error("A Resource Property Element was encountered with a single attribute which was not rdf:ID, only rdf:ID is permitted", element);
                }
                else
                {
                    ID = element.Attributes.First().Value;
                }
            }

            //Next must be an ElementEvent
            if (!(next is ElementEvent))
            {
                throw ParserHelper.Error("Unexpected Event '" + next.GetType().ToString() + "', expected an ElementEvent as the first Event in a Resource Property Elements Event list", next);
            }

            //Get list of Sub Events
            IEventQueue<IRdfXmlEvent> subevents = new EventQueue<IRdfXmlEvent>();
            while (eventlist.Count > 1)
            {
                subevents.Enqueue(eventlist.Dequeue());
            }
            this.GrammarProductionNodeElement(context, subevents);

            //Check Last is an EndElementEvent
            IRdfXmlEvent last = eventlist.Dequeue();
            if (!(last is EndElementEvent))
            {
                throw ParserHelper.Error("Unexpected Event '" + last.GetType().ToString() + "', expected an EndElement Event", last);
            }

            //Now we can generate the relevant RDF
            INode subj, pred, obj;

            //Validate the Type of the Parent
            if (!(parent is ElementEvent))
            {
                throw ParserHelper.Error("Unexpected Parent Event '" + parent.GetType().ToString() + "', expected an ElementEvent", parent);
            }
            ElementEvent parentEl = (ElementEvent)parent;

            //Get the Subject Node from the Parent
            subj = parentEl.SubjectNode;

            //Validate the ID (if any)
            if (!ID.Equals(String.Empty))
            {
                this.ValidateID(context, ID, subj);
            }

            //Create a Predicate from this Element
            pred = this.Resolve(context, element);//context.Handler.CreateUriNode(element.QName);

            //Get the Object Node from the Child Node
            ElementEvent child = (ElementEvent)next;
            obj = child.SubjectNode;

            //Assert the Triple
            if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop();

            //Add Reification where appropriate
            if (element.Attributes.Count == 1)
            {
                //Must be an rdf:ID attribute as we've validated this earlier

                //Get the Attribute Event and generate a Uri from it
                AttributeEvent attr = element.Attributes.First();
                UriReferenceEvent uriref = new UriReferenceEvent("#" + attr.Value, attr.SourceXml);
                IUriNode uri = this.Resolve(context, uriref, element.BaseUri);

                this.Reify(context, uri, subj, pred, obj);
            }
        }
示例#19
0
 /// <summary>
 /// Helper function which generates standardised Error Messages
 /// </summary>
 /// <param name="message">Error Message</param>
 /// <param name="evt">Event causing the Error</param>
 /// <returns></returns>
 public static RdfParseException Error(String message, IRdfXmlEvent evt)
 {
     return Error(message, String.Empty, evt);
 }
示例#20
0
        /// <summary>
        /// Applies List Expansion to the given Event
        /// </summary>
        /// <param name="evt">Element to apply List Expansion to</param>
        /// <returns>Uri Reference for the List Item</returns>
        /// <remarks>List Expansion only works on Element Events</remarks>
        private UriReferenceEvent ListExpand(IRdfXmlEvent evt)
        {
            if (evt is ElementEvent)
            {
                //Cast to an ElementEvent
                ElementEvent e = (ElementEvent)evt;

                //Form a new Uri Reference
                UriReferenceEvent u = new UriReferenceEvent("rdf:_" + e.ListCounter, String.Empty);

                //Increment the List Counter
                e.ListCounter = e.ListCounter + 1;

                //Return the new Uri Reference
                return u;
            }
            else
            {
                throw ParserHelper.Error("Cannot perform List Expansion on an Event which is not an ElementEvent", evt);
            }
        }
示例#21
0
        /// <summary>
        /// Gets the next event from the XML stream
        /// </summary>
        /// <returns></returns>
        public IRdfXmlEvent GetNextEvent()
        {
            if (_stop)
            {
                return(null);
            }

            // If the Root Element is filled then return it
            if (_rootEl != null)
            {
                IRdfXmlEvent temp = _rootEl;
                _rootEl = null;
                return(temp);
            }

            // If Literal Parsing flag is set then we've just read an element which had rdf:parseType="Literal"
            if (_parseLiteral)
            {
                _requireEndElement = true;
                _parseLiteral      = false;
                _noRead            = true;
                _reader.MoveToContent();
                String data = _reader.ReadInnerXml();
                return(new TypedLiteralEvent(data, RdfSpecsHelper.RdfXmlLiteral, data, GetPosition()));
            }

            // If we need to return an end element then do so
            if (_requireEndElement)
            {
                _requireEndElement = false;
                _currentBaseUri    = _baseUris.Pop();
                return(new EndElementEvent(GetPosition()));
            }

            // If at EOF throw an error
            if (_reader.EOF)
            {
                throw new RdfParseException("Unable to read further events as the end of the stream has already been reached");
            }

            // Otherwise attempt to read the next node
            bool read = true;

            if (!_noRead)
            {
                read = _reader.Read();
            }
            else
            {
                _noRead = false;
            }
            if (read)
            {
                // Return the appropriate event for the Node Type
                switch (_reader.NodeType)
                {
                case XmlNodeType.Element:
                    // Element
                    if (_first)
                    {
                        _first       = false;
                        _rdfRootSeen = IsName("RDF", NamespaceMapper.RDF);
                        _rootEl      = GetElement();
                        RootEvent root = new RootEvent(GetBaseUri(), _reader.Value, GetPosition());
                        root.DocumentElement = (ElementEvent)_rootEl;
                        root.Children.Add((ElementEvent)_rootEl);

                        if (root.BaseUri.Equals(String.Empty))
                        {
                            root.BaseUri = _currentBaseUri;
                        }

                        return(root);
                    }
                    else
                    {
                        if (!_first && IsName("RDF", NamespaceMapper.RDF))
                        {
                            if (_rdfRootSeen)
                            {
                                throw new RdfParseException("Unexpected nested rdf:RDF node encountered, this is not valid RDF/XML syntax");
                            }
                            _noRead = true;
                            _first  = true;
                            return(new ClearQueueEvent());
                        }
                        return(GetElement());
                    }

                case XmlNodeType.EndElement:
                    // End of an Element
                    _currentBaseUri = _baseUris.Pop();
                    if (IsName("RDF", NamespaceMapper.RDF))
                    {
                        _stop = true;
                    }
                    return(new EndElementEvent(GetPosition()));

                case XmlNodeType.Attribute:
                    // Attribute
                    throw new RdfParseException("Unexpected Attribute Node encountered");

                case XmlNodeType.Text:
                    return(new TextEvent(_reader.Value, _reader.Value, GetPosition()));

                case XmlNodeType.CDATA:
                    return(new TextEvent(_reader.Value, _reader.Value, GetPosition()));

                case XmlNodeType.Document:
                case XmlNodeType.DocumentType:
                case XmlNodeType.XmlDeclaration:
                case XmlNodeType.Comment:
                case XmlNodeType.ProcessingInstruction:
                case XmlNodeType.Notation:
                case XmlNodeType.Whitespace:
                    // Node Types that don't generate events and just indicate to continue reading
                    return(GetNextEvent());

                default:
                    throw new RdfParseException("Unexpected XML Node Type " + _reader.NodeType.ToString() + " encountered");
                }
            }
            else
            {
                return(null);
            }
        }
示例#22
0
        /// <summary>
        /// Helper function which inserts an Element back on the front of a Queue
        /// </summary>
        /// <param name="eventlist">Queue to insert onto the Front of</param>
        /// <param name="evt">Event to put on the front of the Queue</param>
        private void QueueJump(IEventQueue<IRdfXmlEvent> eventlist, IRdfXmlEvent evt)
        {
            Stack<IRdfXmlEvent> temp = new Stack<IRdfXmlEvent>();
            temp.Push(evt);

            while (eventlist.Count > 0)
            {
                temp.Push(eventlist.Dequeue());
            }

            foreach (IRdfXmlEvent e in temp.Reverse())
            {
                eventlist.Enqueue(e);
            }
        }
示例#23
0
 /// <summary>
 /// Adds an Event to the Queue
 /// </summary>
 /// <param name="e">Event</param>
 public abstract void Enqueue(IRdfXmlEvent e);
示例#24
0
        /// <summary>
        /// Implementation of the RDF/XML Grammar Production 'emptyPropertyElt'
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="element">Element Event for the Empty Property Element</param>
        /// <param name="parent">Parent Event (ie. Node) of the Property Element</param>
        private void GrammarProductionEmptyPropertyElement(RdfXmlParserContext context, ElementEvent element, IRdfXmlEvent parent)
        {
            //Tracing
            if (this._traceparsing)
            {
                this.ProductionTrace("Empty Property Element");
            }

            //Apply Namespaces
            this.ApplyNamespaces(context, element);

            INode subj, pred, obj;
            ElementEvent parentEl;

            //Are there any attributes OR Only a rdf:ID attribute?
            if (element.Attributes.Count == 0 || (element.Attributes.Count == 1 && RdfXmlSpecsHelper.IsIDAttribute(element.Attributes[0])))
            {
                //No Attributes/Only rdf:ID

                //Get the Subject Node from the Parent
                parentEl = (ElementEvent)parent;
                subj = parentEl.SubjectNode;

                //Create the Predicate from the Element
                pred = this.Resolve(context, element);//context.Handler.CreateUriNode(element.QName);

                //Create the Object
                if (!element.Language.Equals(String.Empty))
                {
                    obj = context.Handler.CreateLiteralNode(String.Empty, element.Language);
                }
                else
                {
                    obj = context.Handler.CreateLiteralNode(String.Empty);
                }

                //Make the Assertion
                if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop();

                //Reifiy if applicable
                if (element.Attributes.Count == 1)
                {
                    //Validate the ID
                    this.ValidateID(context, element.Attributes[0].Value, subj);

                    //Resolve the Uri
                    UriReferenceEvent uriref = new UriReferenceEvent("#" + element.Attributes[0].Value, String.Empty);
                    IUriNode uri = this.Resolve(context, uriref, element.BaseUri);

                    this.Reify(context, uri, subj, pred, obj);
                }

            }
            else if (element.Attributes.Count > 0 && element.Attributes.Where(a => RdfXmlSpecsHelper.IsDataTypeAttribute(a)).Count() == 1)
            {
                //Should be processed as a Typed Literal Event instead
                EventQueue<IRdfXmlEvent> temp = new EventQueue<IRdfXmlEvent>();
                temp.Enqueue(element);
                temp.Enqueue(new TextEvent(String.Empty, String.Empty));
                temp.Enqueue(new EndElementEvent());
                this.GrammarProductionLiteralPropertyElement(context, temp, parent);
                return;
            }
            else
            {

                //Check through attributes
                IRdfXmlEvent res = null;

                //Check through attributes to decide the Subject of the Triple(s)
                String ID = String.Empty;
                int limitedAttributes = 0;
                foreach (AttributeEvent a in element.Attributes)
                {
                    if (RdfXmlSpecsHelper.IsResourceAttribute(a))
                    {
                        //An rdf:resource attribute so a Uri Reference
                        res = new UriReferenceEvent(a.Value, a.SourceXml);
                        limitedAttributes++;
                    }
                    else if (RdfXmlSpecsHelper.IsNodeIDAttribute(a))
                    {
                        //An rdf:nodeID attribute so a Blank Node

                        //Validate the Node ID
                        if (!XmlSpecsHelper.IsName(a.Value))
                        {
                            //Invalid nodeID
                            throw ParserHelper.Error("The value '" + a.Value + "' for rdf:nodeID is not valid, RDF Node IDs can only be valid Names as defined by the W3C XML Specification", "Empty Property Element", a);
                        }
                        res = new BlankNodeIDEvent(a.Value, a.SourceXml);
                        limitedAttributes++;
                    }
                    else if (RdfXmlSpecsHelper.IsIDAttribute(a))
                    {
                        //Set the ID for later use in reification
                        ID = "#" + a.Value;
                    }

                    //Check we haven't got more than 1 of the Limited Attributes
                    if (limitedAttributes > 1)
                    {
                        throw ParserHelper.Error("A Property Element can only have 1 of the following attributes: rdf:nodeID or rdf:resource", "Empty Property Element", element);
                    }
                }
                if (res == null)
                {
                    //No relevant attributes so an anonymous Blank Node
                    res = new BlankNodeIDEvent(String.Empty);
                }

                //Now create the actual Subject Node
                if (res is UriReferenceEvent)
                {
                    //Resolve the Uri Reference
                    UriReferenceEvent uriref = (UriReferenceEvent)res;
                    subj = this.Resolve(context, uriref, element.BaseUri);
                }
                else if (res is BlankNodeIDEvent)
                {
                    BlankNodeIDEvent blank = (BlankNodeIDEvent)res;
                    if (blank.Identifier.Equals(String.Empty))
                    {
                        //Have the Graph generate a Blank Node ID
                        subj = context.Handler.CreateBlankNode();
                    }
                    else
                    {
                        //Use the supplied Blank Node ID
                        subj = context.Handler.CreateBlankNode(blank.Identifier);
                    }
                }
                else
                {
                    //Should never hit this case but required to get the Code to Compile
                    //Have the Graph generate a Blank Node ID
                    subj = context.Handler.CreateBlankNode();
                }

                //Validate the ID (if any)
                if (!ID.Equals(String.Empty))
                {
                    this.ValidateID(context, ID.Substring(1), subj);
                }

                //Relate the Property element to its parent
                parentEl = (ElementEvent)parent;
                pred = this.Resolve(context, element);//context.Handler.CreateUriNode(element.QName);
                if (!context.Handler.HandleTriple(new Triple(parentEl.SubjectNode, pred, subj))) ParserHelper.Stop();

                //Reify if applicable
                if (!ID.Equals(String.Empty))
                {
                    //Resolve the Uri
                    UriReferenceEvent uriref = new UriReferenceEvent(ID, String.Empty);
                    IUriNode uri = this.Resolve(context, uriref, element.BaseUri);

                    this.Reify(context, uri, parentEl.SubjectNode, pred, subj);
                }

                //Process the rest of the Attributes
                foreach (AttributeEvent a in element.Attributes)
                {
                    if (a.QName.Equals("rdf:type"))
                    {
                        //A Property Attribute giving a Type

                        //Assert a Type Triple
                        UriReferenceEvent type = new UriReferenceEvent(a.Value, a.SourceXml);
                        pred = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfType));
                        obj = this.Resolve(context, type, element.BaseUri);

                        if (!context.Handler.HandleTriple(new Triple(parentEl.SubjectNode, pred, obj))) ParserHelper.Stop();
                    }
                    else if (RdfXmlSpecsHelper.IsPropertyAttribute(a))
                    {
                        //A Property Attribute

                        //Validate the Normalization of the Attribute Value
            #if !NO_NORM
                        if (!a.Value.IsNormalized())
                        {
                            throw ParserHelper.Error("Encountered a Property Attribute '" + a.QName + "' whose value was not correctly normalized in Unicode Normal Form C", "Empty Property Element", a);
                        }
                        else
                        {
            #endif
                            //Create the Predicate from the Attribute QName
                            pred = context.Handler.CreateUriNode(UriFactory.Create(Tools.ResolveQName(a.QName, context.Namespaces, context.BaseUri)));

                            //Create the Object from the Attribute Value
                            if (element.Language.Equals(String.Empty))
                            {
                                obj = context.Handler.CreateLiteralNode(a.Value);
                            }
                            else
                            {
                                obj = context.Handler.CreateLiteralNode(a.Value, element.Language);
                            }

                            //Assert the Property Triple
                            if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop();
            #if !NO_NORM
                        }
            #endif
                    }
                    else if (RdfXmlSpecsHelper.IsIDAttribute(a) || RdfXmlSpecsHelper.IsNodeIDAttribute(a) || RdfXmlSpecsHelper.IsResourceAttribute(a))
                    {
                        //These have already been processed
                        //We test for them so that we can then throw ParserHelper.Errors in the final case for unexpected attributes
                    }
                    else
                    {
                        //Unexpected Attribute
                        throw ParserHelper.Error("Unexpected Attribute '" + a.QName + "' encountered on a Property Element!  Only rdf:ID, rdf:resource, rdf:nodeID and Property Attributes are permitted on Property Elements", "Empty Property Element", element);
                    }
                }
            }
        }