/// <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); } }
/// <summary> /// Implementation of the RDF/XML Grammar Production 'nodeElement' /// </summary> /// <param name="context">Parser Context</param> /// <param name="eventlist">Queue of Events that make up the Node Element and its Children to apply the Production to</param> private void GrammarProductionNodeElement(RdfXmlParserContext context, IEventQueue<IRdfXmlEvent> eventlist) { //Tracing if (this._traceparsing) { this.ProductionTracePartial("Node Element"); } //Get First Event in the Queue IRdfXmlEvent first = eventlist.Dequeue(); //Check it's an ElementEvent if (!(first is ElementEvent)) { //Unexpected Event throw ParserHelper.Error("Expected an ElementEvent but encountered a '" + first.GetType().ToString() + "'", "Node Element", first); } //Check it has a valid Uri ElementEvent element = (ElementEvent)first; if (this._traceparsing) this.ProductionTracePartial(element); this.ApplyNamespaces(context, element); if (!RdfXmlSpecsHelper.IsNodeElementUri(element.QName)) { throw ParserHelper.Error("A Node Element was encountered with an invalid URI '" + element.QName + "' \nCore Syntax Terms, Old Syntax Terms and rdf:li cannot be used as Node Element URIs", "Node Element", element); } //Check the set of Attributes is Valid int limitedAttributesFound = 0; String ID = String.Empty; foreach (AttributeEvent attr in element.Attributes) { if (RdfXmlSpecsHelper.IsIDAttribute(attr)) { ID = attr.Value; limitedAttributesFound++; //Set the Subject element.Subject = new UriReferenceEvent("#" + attr.Value, attr.SourceXml); } else if (RdfXmlSpecsHelper.IsNodeIDAttribute(attr)) { limitedAttributesFound++; //Validate the Node ID if (!XmlSpecsHelper.IsName(attr.Value)) { throw ParserHelper.Error("The value '" + attr.Value + "' for rdf:nodeID is not valid, RDF Node IDs can only be valid Names as defined by the W3C XML Specification", "Node Element", attr); } //Set the Subject element.Subject = new BlankNodeIDEvent(attr.Value, attr.SourceXml); } else if (RdfXmlSpecsHelper.IsAboutAttribute(attr)) { limitedAttributesFound++; //Set the Subject element.Subject = new UriReferenceEvent(attr.Value, attr.SourceXml); } else if (RdfXmlSpecsHelper.IsPropertyAttribute(attr)) { //Don't need to do anything here yet } else { //Unknown and Unexpected Attribute Type throw ParserHelper.Error("Unexpected Attribute '" + attr.QName + "' was encountered!", "Node Element", element); } //Can't have more than 1 of ID, Node ID or About Attributes if (limitedAttributesFound > 1) { throw ParserHelper.Error("A Node Element can only have 1 of the following attributes: rdf:id, rdf:nodeID, rdf:about", "Node Element", element); } } //Generate a Blank Node ID if our Subject is empty if (element.Subject == null) { element.Subject = new BlankNodeIDEvent(element.SourceXml); } //Add statements as necessary INode subj, pred, obj; if (element.SubjectNode == null) { //Don't always want to drop in here since the SubjectNode may already be set elsewhere if (element.Subject is UriReferenceEvent) { UriReferenceEvent uri = (UriReferenceEvent)element.Subject; subj = this.Resolve(context, uri, element.BaseUri); } else if (element.Subject is BlankNodeIDEvent) { BlankNodeIDEvent blank = (BlankNodeIDEvent)element.Subject; //Select whether we need to generate an ID or if there's one given for the Blank Node //Note that we let the Graph class handle generation of IDs if (blank.Identifier.Equals(String.Empty)) { subj = context.Handler.CreateBlankNode(); } else { subj = context.Handler.CreateBlankNode(blank.Identifier); } } else { throw ParserHelper.Error("Unexpected Subject generated for a Triple", "Node Element", element.Subject); } } else { subj = element.SubjectNode; } //Set the Subject Node property of the Event for later reuse element.SubjectNode = subj; //Validate the ID (if any) if (!ID.Equals(String.Empty)) { this.ValidateID(context, ID, subj); } if (!element.QName.Equals("rdf:Description") && !element.QName.Equals(":Description")) { //Assert a Triple regarding Type pred = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfType)); obj = this.Resolve(context, element);//context.Handler.CreateUriNode(element.QName); if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop(); } //Go back over Attributes looking for property attributes foreach (AttributeEvent attr in element.Attributes) { if (RdfXmlSpecsHelper.IsPropertyAttribute(attr)) { if (attr.QName.Equals("rdf:type")) { //Generate a Type Triple pred = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfType)); //Resolve URIRef into a Uri Node UriReferenceEvent uriref = new UriReferenceEvent(attr.Value, attr.SourceXml); obj = this.Resolve(context, uriref, element.BaseUri); if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop(); } else { //Generate a Property Triple pred = context.Handler.CreateUriNode(UriFactory.Create(Tools.ResolveQName(attr.QName, context.Namespaces, context.BaseUri))); //Add Language to Literal if necessary if (element.Language.Equals(String.Empty)) { obj = context.Handler.CreateLiteralNode(attr.Value); } else { obj = context.Handler.CreateLiteralNode(attr.Value, element.Language); } if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) ParserHelper.Stop(); } } } //Handle Child Elements IEventQueue<IRdfXmlEvent> children = new EventQueue<IRdfXmlEvent>(); while (eventlist.Count > 1) { children.Enqueue(eventlist.Dequeue()); } if (children.Count > 0) this.GrammarProductionPropertyElementList(context, children, element); //Check Last Event in queue is an EndElement event IRdfXmlEvent last = eventlist.Dequeue(); if (!(last is EndElementEvent)) { throw ParserHelper.Error("Unexpected Event '" + last.GetType().ToString() + "', expected an EndElement Event", "NodeElement", last); } }
/// <summary> /// Implementation of the RDF/XML Grammar Production 'nodeElementList' /// </summary> /// <param name="context">Parser Context</param> /// <param name="eventlist">Queue of Events to apply the Production to</param> private void GrammarProductionNodeElementList(RdfXmlParserContext context, IEventQueue<IRdfXmlEvent> eventlist) { //Tracing if (this._traceparsing) { this.ProductionTrace("Node 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 this.GrammarProductionNodeElement(context, subevents); } }
/// <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); } } } }
/// <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); } }
/// <summary> /// Implementation of the RDF/XML Grammar Production 'RDF' /// </summary> /// <param name="context">Parser Context</param> /// <param name="element">RDF Element to apply Production to</param> private void GrammarProductionRDF(RdfXmlParserContext context, ElementEvent element) { //Tracing if (this._traceparsing) { this.ProductionTrace("RDF", element); } //Check Uri is correct String localName = element.LocalName; String prefix = element.Namespace; if (localName.Equals("RDF") || ((context.Namespaces.HasNamespace(prefix) && context.Namespaces.GetNamespaceUri(prefix).ToString().Equals(NamespaceMapper.RDF)) || element.NamespaceAttributes.Any(ns => ns.Prefix.Equals(prefix) && ns.Uri.Equals(NamespaceMapper.RDF)))) { //This is OK } else { throw ParserHelper.Error("Unexpected Node '" + element.QName + "', an 'rdf:RDF' node was expected", "RDF", element); } //Check has no Attributes if (element.Attributes.Count > 0) { throw ParserHelper.Error("Root Node should not contain any attributes other than XML Namespace Declarations", "RDF", element); } //Apply Namespaces this.ApplyNamespaces(context, element); //Build a Sublist of all Nodes up to the matching EndElement IEventQueue<IRdfXmlEvent> subevents = new EventQueue<IRdfXmlEvent>(); IRdfXmlEvent next; //Make sure we discard the current ElementEvent which will be at the front of the queue context.Events.Dequeue(); //Gather the Sublist while (context.Events.Count > 1) { subevents.Enqueue(context.Events.Dequeue()); } //Call the NodeElementList Grammer Production this.GrammarProductionNodeElementList(context, subevents); //Next Event in queue should be an EndElementEvent or we Error next = context.Events.Dequeue(); if (!(next is EndElementEvent)) { throw ParserHelper.Error("Unexpected Event '" + next.GetType().ToString() + "', an EndElementEvent was expected", "RDF", element); } }
/// <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); } }
/// <summary> /// Implementation of the RDF/XML Grammar Production 'RDF' /// </summary> /// <param name="context">Parser Context</param> /// <param name="element">RDF Element to apply Production to</param> private void GrammarProductionRDF(RdfXmlParserContext context, ElementEvent element) { //Tracing if (this._traceparsing) { this.ProductionTrace("RDF"); } //Check Uri is correct (using the QName for simplicity) if (!element.QName.Equals("rdf:RDF") && !element.QName.Equals(":RDF")) { throw ParserHelper.Error("Unexpected Node '" + element.QName + "', an 'rdf:RDF' node was expected", "RDF", element); } //Check has no Attributes if (element.Attributes.Count > 0) { throw ParserHelper.Error("Root Node should not contain any attributes other than XML Namespace Declarations", "RDF", element); } //Apply Namespaces this.ApplyNamespaces(context, element); //Build a Sublist of all Nodes up to the matching EndElement IEventQueue subevents = new EventQueue(); IRdfXmlEvent next; //Make sure we discard the current ElementEvent which will be at the front of the queue context.Events.Dequeue(); //Gather the Sublist while (context.Events.Count > 1) { subevents.Enqueue(context.Events.Dequeue()); } //Call the NodeElementList Grammer Production this.GrammarProductionNodeElementList(context, subevents); //Next Event in queue should be an EndElementEvent or we Error next = context.Events.Dequeue(); if (!(next is EndElementEvent)) { throw ParserHelper.Error("Unexpected Event '" + next.GetType().ToString() + "', an EndElementEvent was expected", "RDF", element); } }