Пример #1
0
        private SparqlUpdateCommand TryParseInsertCommand(SparqlUpdateParserContext context, bool allowData)
        {
            List <Uri> usings     = new List <Uri>();
            List <Uri> usingNamed = new List <Uri>();
            IToken     next       = context.Tokens.Dequeue();

            if (allowData)
            {
                //We are allowed to have an INSERT DATA command here so check for it
                if (next.TokenType == Token.DATA)
                {
                    return(this.TryParseInsertDataCommand(context));
                }
            }
            else
            {
                if (next.TokenType == Token.DATA)
                {
                    throw ParserHelper.Error("The DATA keyword is not permitted here as this INSERT command forms part of a modification command", next);
                }
            }

            //Get the Modification Template
            GraphPattern insertions = this.TryParseModifyTemplate(context);

            //Then we expect a WHERE keyword
            next = context.Tokens.Dequeue();
            if (next.TokenType == Token.USING)
            {
                foreach (KeyValuePair <Uri, bool> kvp in this.TryParseUsingStatements(context))
                {
                    if (kvp.Value)
                    {
                        usingNamed.Add(kvp.Key);
                    }
                    else
                    {
                        usings.Add(kvp.Key);
                    }
                }
                next = context.Tokens.Dequeue();
            }
            if (next.TokenType != Token.WHERE)
            {
                throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a WHERE keyword as part of a INSERT command", next);
            }

            //Now parse the WHERE pattern
            SparqlQueryParserContext subContext = new SparqlQueryParserContext(context.Tokens);

            subContext.Query.BaseUri                        = context.BaseUri;
            subContext.Query.NamespaceMap                   = context.NamespaceMap;
            subContext.ExpressionParser.NamespaceMap        = context.NamespaceMap;
            subContext.ExpressionParser.ExpressionFactories = context.ExpressionFactories;
            subContext.ExpressionFactories                  = context.ExpressionFactories;
            GraphPattern where = context.QueryParser.TryParseGraphPattern(subContext, context.Tokens.LastTokenType != Token.LEFTCURLYBRACKET);

            //And finally return the command
            InsertCommand cmd = new InsertCommand(insertions, where);

            usings.ForEach(u => cmd.AddUsingUri(u));
            usingNamed.ForEach(u => cmd.AddUsingNamedUri(u));
            return(cmd);
        }
Пример #2
0
        private void TryParseTransferUris(SparqlUpdateParserContext context, out Uri sourceUri, out Uri destUri)
        {
            IToken next = context.Tokens.Peek();

            sourceUri = destUri = null;

            //Parse the Source Graph URI
            if (next.TokenType == Token.GRAPH)
            {
                context.Tokens.Dequeue();
                next = context.Tokens.Peek();
                if (next.TokenType == Token.URI || next.TokenType == Token.QNAME)
                {
                    sourceUri = this.TryParseIriRef(context, " to indicate the Source Graph for a Transfer (ADD/COPY/MOVE) command");
                }
                else
                {
                    ParserHelper.Error("Unexpected Token '" + next.GetType().Name + "' encountered, expected a URI/QName after a GRAPH keyword to specify the URI of the Source Graph for a Transfer (ADD/COPY/MOVE) Command", next);
                }
            }
            else if (next.TokenType == Token.URI || next.TokenType == Token.QNAME)
            {
                //May have a URI/QName for a Graph without a GRAPH keyword
                sourceUri = this.TryParseIriRef(context, " to indicate the Source Graph for a Transfer (ADD/COPY/MOVE) command");
            }
            else if (next.TokenType == Token.DEFAULT)
            {
                context.Tokens.Dequeue();
                sourceUri = null;
            }
            else
            {
                throw ParserHelper.Error("Unexpected Token '" + next.GetType().Name + "' encountered, expected a GRAPH/DEFAULT keyword to indicate the Source Graph for a Transfer (ADD/COPY/MOVE) Command", next);
            }

            //Then get the TO keyword
            next = context.Tokens.Dequeue();
            if (next.TokenType != Token.TO)
            {
                throw ParserHelper.Error("Unexpected Token '" + next.GetType().Name + "' encountered, expected a TO Keyword after the Source Graph specifier", next);
            }

            next = context.Tokens.Peek();

            //Parse the Destination Graph URI
            if (next.TokenType == Token.GRAPH)
            {
                context.Tokens.Dequeue();
                next = context.Tokens.Peek();
                if (next.TokenType == Token.URI || next.TokenType == Token.QNAME)
                {
                    destUri = this.TryParseIriRef(context, " to indicate the Destination Graph for a Transfer (ADD/COPY/MOVE) command");
                }
                else
                {
                    ParserHelper.Error("Unexpected Token '" + next.GetType().Name + "' encountered, expected a URI/QName after a GRAPH keyword to specify the URI of the Destination Graph for a Transfer (ADD/COPY/MOVE) Command", next);
                }
            }
            else if (next.TokenType == Token.URI || next.TokenType == Token.QNAME)
            {
                //May have a URI/QName for a Graph without a GRAPH keyword
                destUri = this.TryParseIriRef(context, " to indicate the Destination Graph for a Transfer (ADD/COPY/MOVE) command");
            }
            else if (next.TokenType == Token.DEFAULT)
            {
                context.Tokens.Dequeue();
                destUri = null;
            }
            else
            {
                throw ParserHelper.Error("Unexpected Token '" + next.GetType().Name + "' encountered, expected a GRAPH/DEFAULT keyword to indicate the Destination Graph for a Transfer (ADD/COPY/MOVE) Command", next);
            }
        }
Пример #3
0
        private SparqlUpdateCommandSet ParseInternal(SparqlUpdateParserContext context)
        {
            //Set up the Context appropriately
            context.BaseUri = this.DefaultBaseUri;
            context.QueryParser.ExpressionFactories      = context.ExpressionFactories;
            context.QueryParser.DefaultBaseUri           = this.DefaultBaseUri;
            context.ExpressionParser.BaseUri             = this.DefaultBaseUri;
            context.ExpressionParser.NamespaceMap        = context.NamespaceMap;
            context.ExpressionParser.QueryParser         = context.QueryParser;
            context.ExpressionParser.ExpressionFactories = context.ExpressionFactories;
            context.Tokens.InitialiseBuffer();

            IToken next;
            bool   commandParsed = false;

            do
            {
                next = context.Tokens.Dequeue();
                switch (next.TokenType)
                {
                case Token.BOF:
                case Token.COMMENT:
                    //Discardable Tokens
                    break;

                case Token.EOF:
                    if (next.StartLine == 1 && next.StartPosition == 1)
                    {
                        throw new RdfParseException("Empty SPARQL Updates are not permitted");
                    }
                    break;

                case Token.BASEDIRECTIVE:
                    this.TryParseBaseDeclaration(context);
                    break;

                case Token.PREFIXDIRECTIVE:
                    this.TryParsePrefixDeclaration(context);
                    break;

                case Token.ADD:
                    this.TryParseAddCommand(context);
                    commandParsed = true;
                    break;

                case Token.CLEAR:
                    this.TryParseClearCommand(context);
                    commandParsed = true;
                    break;

                case Token.COPY:
                    this.TryParseCopyCommand(context);
                    commandParsed = true;
                    break;

                case Token.CREATE:
                    this.TryParseCreateCommand(context);
                    commandParsed = true;
                    break;

                case Token.DROP:
                    this.TryParseDropCommand(context);
                    commandParsed = true;
                    break;

                case Token.DELETE:
                    context.CommandSet.AddCommand(this.TryParseDeleteCommand(context, true));
                    commandParsed = true;
                    break;

                case Token.INSERT:
                    context.CommandSet.AddCommand(this.TryParseInsertCommand(context, true));
                    commandParsed = true;
                    break;

                case Token.LOAD:
                    this.TryParseLoadCommand(context);
                    commandParsed = true;
                    break;

                case Token.MOVE:
                    this.TryParseMoveCommand(context);
                    commandParsed = true;
                    break;

                case Token.WITH:
                    this.TryParseModifyCommand(context);
                    commandParsed = true;
                    break;

                default:
                    throw ParserHelper.Error("Unexpected Token encountered", next);
                }

                if (commandParsed)
                {
                    //After a Command we expect to see either a separator or EOF
                    next = context.Tokens.Dequeue();
                    if (next.TokenType != Token.SEMICOLON && next.TokenType != Token.EOF)
                    {
                        throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a semicolon separator or EOF after a command", next);
                    }

                    commandParsed = false;
                }
            } while (next.TokenType != Token.EOF);

            //Optimise the Command Set before returning it
            context.CommandSet.Optimise();
            return(context.CommandSet);
        }
Пример #4
0
        private void TryParseCollection(TriGParserContext context, Uri graphUri, INode subj)
        {
            //Create the Nodes we need
            IUriNode rdfFirst, rdfRest, rdfNil;

            rdfFirst = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListFirst));
            rdfRest  = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListRest));
            rdfNil   = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil));

            IToken next;
            INode  item, temp;

            item = null;
            do
            {
                next = context.Tokens.Dequeue();

                //Create a Node for this Token
                switch (next.TokenType)
                {
                case Token.COMMENT:
                    //Discard and continue;
                    continue;

                case Token.QNAME:
                case Token.URI:
                    item = ParserHelper.TryResolveUri(context, next);
                    break;

                case Token.LITERAL:
                case Token.LONGLITERAL:

                    break;

                case Token.PLAINLITERAL:
                    Uri plt = TurtleSpecsHelper.InferPlainLiteralType((PlainLiteralToken)next, TurtleSyntax.Original);
                    item = context.Handler.CreateLiteralNode(next.Value, plt);
                    break;

                case Token.LEFTSQBRACKET:
                    //Check whether an anonymous Blank Node or a Blank Node Collection
                    item = context.Handler.CreateBlankNode();

                    next = context.Tokens.Peek();
                    if (next.TokenType == Token.RIGHTSQBRACKET)
                    {
                        //Anonymous Blank Node
                        context.Tokens.Dequeue();
                    }
                    else
                    {
                        //Blank Node Collection
                        this.TryParsePredicateObjectList(context, graphUri, item);
                    }
                    break;

                case Token.LEFTBRACKET:
                    //Check whether an Empty Collection
                    next = context.Tokens.Peek();
                    if (next.TokenType == Token.RIGHTBRACKET)
                    {
                        //Empty Collection
                        context.Tokens.Dequeue();
                        item = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil));
                    }
                    else
                    {
                        //Collection
                        item = context.Handler.CreateBlankNode();
                        this.TryParseCollection(context, graphUri, item);
                    }
                    break;

                case Token.EOF:
                    throw ParserHelper.Error("Unexpected End of File while trying to parse a Collection", next);

                default:
                    //Unexpected Token
                    throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a URI/QName/Literal/Blank Node as an item in a Collection", next);
                }

                //Create the subj rdf:first item Triple
                if (!context.Handler.HandleTriple((new Triple(subj, rdfFirst, item, graphUri))))
                {
                    ParserHelper.Stop();
                }

                //Create the rdf:rest Triple
                if (context.Tokens.Peek().TokenType == Token.RIGHTBRACKET)
                {
                    //End of Collection
                    context.Tokens.Dequeue();
                    if (!context.Handler.HandleTriple(new Triple(subj, rdfRest, rdfNil, graphUri)))
                    {
                        ParserHelper.Stop();
                    }
                    return;
                }
                else
                {
                    //Continuing Collection
                    temp = context.Handler.CreateBlankNode();
                    if (!context.Handler.HandleTriple(new Triple(subj, rdfRest, temp, graphUri)))
                    {
                        ParserHelper.Stop();
                    }
                    subj = temp;
                }
            } while (true);
        }
Пример #5
0
        /// <summary>
        /// Internal method which actually parses the Result Set by traversing the RDF Graph appropriately.
        /// </summary>
        /// <param name="context">Parser Context.</param>
        private void Parse(SparqlRdfParserContext context)
        {
            try
            {
                context.Handler.StartResults();

                // Create relevant Nodes
                context.Graph.NamespaceMap.AddNamespace("rdf", UriFactory.Create(NamespaceMapper.RDF));
                context.Graph.NamespaceMap.AddNamespace("rs", UriFactory.Create(SparqlSpecsHelper.SparqlRdfResultsNamespace));
                IUriNode rdfType        = context.Graph.CreateUriNode("rdf:type");
                IUriNode resultSetClass = context.Graph.CreateUriNode("rs:ResultSet");
                IUriNode resultVariable = context.Graph.CreateUriNode("rs:resultVariable");
                IUriNode solution       = context.Graph.CreateUriNode("rs:solution");
                IUriNode binding        = context.Graph.CreateUriNode("rs:binding");
                IUriNode value          = context.Graph.CreateUriNode("rs:value");
                IUriNode variable       = context.Graph.CreateUriNode("rs:variable");
                IUriNode boolean        = context.Graph.CreateUriNode("rs:boolean");

                // Try to get a ResultSet object
                Triple rset = context.Graph.Triples.WithPredicateObject(rdfType, resultSetClass).FirstOrDefault();
                if (rset != null)
                {
                    INode rsetID = rset.Subject;

                    // Find the Variables the Result Set contains or the Boolean Value
                    List <Triple> temp = context.Graph.Triples.WithSubjectPredicate(rsetID, boolean).ToList();
                    if (temp.Count > 0)
                    {
                        if (temp.Count > 1)
                        {
                            throw new RdfParseException("Result Set has more than one boolean result defined for it");
                        }

                        Triple booleanResult = temp.First();
                        INode  result        = booleanResult.Object;
                        if (result.NodeType == NodeType.Literal)
                        {
                            ILiteralNode lit = (ILiteralNode)result;
                            if (lit.DataType != null)
                            {
                                if (lit.DataType.AbsoluteUri.Equals(XmlSpecsHelper.XmlSchemaDataTypeBoolean))
                                {
                                    bool b;
                                    if (Boolean.TryParse(lit.Value, out b))
                                    {
                                        context.Handler.HandleBooleanResult(b);
                                        return;
                                    }
                                    else
                                    {
                                        throw new RdfParseException("Result Set has a boolean result which is a Literal typed as boolean but which does not contain a valid boolean value");
                                    }
                                }
                                else
                                {
                                    throw new RdfParseException("Result Set has a boolean result which is a Literal which is not boolean typed");
                                }
                            }
                            else
                            {
                                throw new RdfParseException("Result Set has a boolean result which is a Literal which is not typed as a boolean");
                            }
                        }
                        else
                        {
                            throw new RdfParseException("Result Set has a boolean result which is not a Literal Node");
                        }
                    }
                    else
                    {
                        // We're expected one/more variables
                        temp = context.Graph.Triples.WithSubjectPredicate(rsetID, resultVariable).ToList();
                        if (temp.Count > 0)
                        {
                            foreach (Triple t in temp)
                            {
                                if (t.Object.NodeType == NodeType.Literal)
                                {
                                    if (!context.Handler.HandleVariable(((ILiteralNode)t.Object).Value))
                                    {
                                        ParserHelper.Stop();
                                    }
                                    context.Variables.Add(((ILiteralNode)t.Object).Value);
                                }
                                else
                                {
                                    throw new RdfParseException("Result Set has a result variable definition which is not a Literal Node");
                                }
                            }
                        }
                        else
                        {
                            throw new RdfParseException("Result Set does not define any result variables or a boolean result");
                        }

                        // Then we're expecting some Solutions
                        temp = context.Graph.Triples.WithSubjectPredicate(rsetID, solution).ToList();
                        foreach (Triple slnTriple in temp)
                        {
                            // Each Solution has some Bindings
                            INode        slnID = slnTriple.Object;
                            bool         ok    = false;
                            SparqlResult r     = new SparqlResult();

                            foreach (Triple bindingTriple in context.Graph.Triples.WithSubjectPredicate(slnID, binding))
                            {
                                // Each Binding has a Variable and a Value
                                ok = true;
                                INode  bindingID = bindingTriple.Object;
                                String var       = String.Empty;
                                INode  val       = null;

                                // Retrieve the Variable and the Bound Value
                                foreach (Triple valueTriple in context.Graph.Triples.WithSubject(bindingID))
                                {
                                    if (valueTriple.Predicate.Equals(variable))
                                    {
                                        if (!var.Equals(String.Empty))
                                        {
                                            throw new RdfParseException("Result Set contains a Binding which refers to more than one Variable");
                                        }
                                        if (valueTriple.Object.NodeType != NodeType.Literal)
                                        {
                                            throw new RdfParseException("Result Set contains a Binding which refers to a Variable but not by a Literal Node as required");
                                        }
                                        var = ((ILiteralNode)valueTriple.Object).Value;
                                    }
                                    else if (valueTriple.Predicate.Equals(value))
                                    {
                                        if (val != null)
                                        {
                                            throw new RdfParseException("Result Set contains a Binding which has more than one Value");
                                        }
                                        val = valueTriple.Object;
                                    }
                                }
                                if (var.Equals(String.Empty) || val == null)
                                {
                                    throw new RdfParseException("Result Set contains a Binding which doesn't contain both a Variable and a Value");
                                }

                                // Check that the Variable was defined in the Header
                                if (!context.Variables.Contains(var))
                                {
                                    throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!");
                                }

                                r.SetValue(var, val);
                            }
                            if (!ok)
                            {
                                throw new RdfParseException("Result Set contains a Solution which has no Bindings");
                            }

                            // Check that all Variables are bound for a given result binding nulls where appropriate
                            foreach (String v in context.Variables)
                            {
                                if (!r.HasValue(v))
                                {
                                    r.SetValue(v, null);
                                }
                            }

                            if (!context.Handler.HandleResult(r))
                            {
                                ParserHelper.Stop();
                            }
                        }
                    }
                }
                else
                {
                    throw new RdfParseException("No Result Set object is defined in the Graph");
                }

                context.Handler.EndResults(true);
            }
            catch (RdfParsingTerminatedException)
            {
                context.Handler.EndResults(true);
            }
            catch
            {
                context.Handler.EndResults(false);
                throw;
            }
        }
Пример #6
0
        private void TryParsePredicateObjectList(TriGParserContext context, Uri graphUri, INode subj)
        {
            bool ok = false;

            do
            {
                //After our first run through we'll need to discard semicolons here
                if (ok)
                {
                    context.Tokens.Dequeue();

                    //Watch out for Trailing Semicolons
                    if (context.Tokens.Peek().TokenType == Token.RIGHTSQBRACKET)
                    {
                        //Allow trailing semicolons to terminate Blank Node Collections
                        context.Tokens.Dequeue();
                        return;
                    }
                }

                //Try to get the Predicate
                IToken pred = context.Tokens.Dequeue();
                INode  predNode;

                switch (pred.TokenType)
                {
                case Token.COMMENT:
                    //Discard and continue
                    ok = false;
                    continue;

                case Token.QNAME:
                case Token.URI:
                    predNode = ParserHelper.TryResolveUri(context, pred);
                    break;

                case Token.KEYWORDA:
                    //'a' Keyword
                    predNode = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfType));
                    break;

                case Token.EOF:
                    throw ParserHelper.Error("Unexpected End of File while trying to parse Predicate Object list", pred);

                case Token.DOT:
                case Token.RIGHTCURLYBRACKET:
                    if (!ok)
                    {
                        throw ParserHelper.Error("Unexpected Token '" + pred.GetType().ToString() + "' encountered before a Predicate Object list was parsed", pred);
                    }
                    return;

                case Token.RIGHTSQBRACKET:
                    if (!ok)
                    {
                        throw ParserHelper.Error("Unexpected Token '" + pred.GetType().ToString() + "' encountered before a Predicate Object list of a Blank Node Collection was parsed", pred);
                    }
                    return;

                default:
                    //Unexpected Token
                    throw ParserHelper.Error("Unexpected Token '" + pred.GetType().ToString() + "' encountered, expected a URI/QName as the Predicate of a Triple", pred);
                }

                ok = true;

                //Parse the Object List
                this.TryParseObjectList(context, graphUri, subj, predNode);

                //Return if we hit the Dot Token/Right Curly Bracket/Right Square Bracket
                if (context.Tokens.LastTokenType == Token.DOT ||
                    context.Tokens.LastTokenType == Token.RIGHTCURLYBRACKET ||
                    context.Tokens.LastTokenType == Token.RIGHTSQBRACKET)
                {
                    return;
                }

                //Check for End of Blank Node Collections
                if (context.Tokens.Peek().TokenType == Token.RIGHTSQBRACKET)
                {
                    context.Tokens.Dequeue();
                    return;
                }
            } while (context.Tokens.Peek().TokenType == Token.SEMICOLON); //Expect a semicolon if we are to continue
        }
Пример #7
0
        private void TryParseObjectList(TriGParserContext context, Uri graphUri, INode subj, INode pred)
        {
            bool ok = false;

            do
            {
                //After the first run through we'll need to discard commas here
                if (ok)
                {
                    context.Tokens.Dequeue();
                }

                //Try to get the Object
                IToken obj = context.Tokens.Dequeue();
                IToken next;
                INode  objNode;

                switch (obj.TokenType)
                {
                case Token.COMMENT:
                    //Discard and Continue
                    ok = false;
                    continue;

                case Token.QNAME:
                case Token.URI:
                    objNode = ParserHelper.TryResolveUri(context, obj);
                    break;

                case Token.LITERAL:
                case Token.LONGLITERAL:
                    //Literals

                    //See whether we get a Language Specifier/Data Type next
                    next = context.Tokens.Peek();
                    if (next.TokenType == Token.LANGSPEC)
                    {
                        //Literal with Language Specifier
                        context.Tokens.Dequeue();
                        objNode = context.Handler.CreateLiteralNode(obj.Value, next.Value);
                    }
                    else if (next.TokenType == Token.HATHAT)
                    {
                        //Literal with DataType
                        context.Tokens.Dequeue();
                        //Now expect a QName/Uri Token
                        next = context.Tokens.Dequeue();
                        if (next.TokenType == Token.QNAME || next.TokenType == Token.URI)
                        {
                            Uri dt = UriFactory.Create(Tools.ResolveUriOrQName(next, context.Namespaces, context.BaseUri));
                            objNode = context.Handler.CreateLiteralNode(obj.Value, dt);
                        }
                        else
                        {
                            throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a URI/QName Token to specify a Data Type after a ^^ Token", next);
                        }
                    }
                    else
                    {
                        //Just a string literal
                        objNode = context.Handler.CreateLiteralNode(obj.Value);
                    }
                    break;

                case Token.PLAINLITERAL:
                    //Plain Literals
                    Uri plt = TurtleSpecsHelper.InferPlainLiteralType((PlainLiteralToken)obj, TurtleSyntax.Original);
                    objNode = context.Handler.CreateLiteralNode(obj.Value, plt);
                    break;

                case Token.BLANKNODEWITHID:
                    //Blank Node with ID
                    objNode = context.Handler.CreateBlankNode(obj.Value.Substring(2));
                    break;

                case Token.LEFTSQBRACKET:
                    //Blank Node
                    next = context.Tokens.Peek();
                    if (next.TokenType == Token.RIGHTSQBRACKET)
                    {
                        //Anonymous Blank Node
                        context.Tokens.Dequeue();
                        objNode = context.Handler.CreateBlankNode();
                    }
                    else
                    {
                        //Blank Node Collection
                        objNode = context.Handler.CreateBlankNode();

                        //Do an extra call to TryParsePredicateObjectList to parse the Blank Node Collection
                        this.TryParsePredicateObjectList(context, graphUri, objNode);
                    }
                    break;

                case Token.RIGHTSQBRACKET:
                    //End of Blank Node Collection
                    if (!ok)
                    {
                        throw ParserHelper.Error("Unexpected Token '" + obj.GetType().ToString() + "' encountered before an Object list of a Blank Node Collection was parsed", obj);
                    }
                    return;

                case Token.LEFTBRACKET:
                    //Collection

                    //Check whether an Empty Collection
                    next = context.Tokens.Peek();
                    if (next.TokenType == Token.RIGHTBRACKET)
                    {
                        //Empty Collection
                        context.Tokens.Dequeue();
                        objNode = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil));
                    }
                    else
                    {
                        //Collection
                        objNode = context.Handler.CreateBlankNode();
                        this.TryParseCollection(context, graphUri, objNode);
                    }
                    break;

                case Token.EOF:
                    throw ParserHelper.Error("Unexpected End of File while trying to parse Object List", obj);

                case Token.DOT:
                case Token.RIGHTCURLYBRACKET:
                case Token.SEMICOLON:
                    if (!ok)
                    {
                        throw ParserHelper.Error("Unexpected Token '" + obj.GetType().ToString() + "' encountered before an Object list was parsed", obj);
                    }
                    return;

                default:
                    //Unexpected Token
                    throw ParserHelper.Error("Unexpected Token '" + obj.GetType().ToString() + "' encountered, expected a URI/QName/Blank Node as the Object of a Triple", obj);
                }

                ok = true;

                if (!context.Handler.HandleTriple(new Triple(subj, pred, objNode, graphUri)))
                {
                    ParserHelper.Stop();
                }
            } while (context.Tokens.Peek().TokenType == Token.COMMA); //Expect a comma if we are to continue
        }
Пример #8
0
        private void TryParseGraph(TriGParserContext context)
        {
            //Is there a name for the Graph?
            IToken next = context.Tokens.Dequeue();
            Uri    graphUri;

            if (next.TokenType == Token.QNAME)
            {
                //Try to resolve the QName
                graphUri = UriFactory.Create(Tools.ResolveQName(next.Value, context.Namespaces, null));

                //Get the Next Token
                next = context.Tokens.Dequeue();
            }
            else if (next.TokenType == Token.URI)
            {
                try
                {
                    //Ensure an absolute Uri
                    graphUri = new Uri(next.Value, UriKind.Absolute);
                }
                catch (UriFormatException)
                {
                    throw ParserHelper.Error("The URI '" + next.Value + "' given as a Graph Name is not a valid Absolute URI", next);
                }

                //Get the Next Token
                next = context.Tokens.Dequeue();
            }
            else
            {
                //No Name so is a Default Graph
                if (!context.DefaultGraphExists)
                {
                    graphUri = null;
                }
                else
                {
                    throw new RdfParseException("You cannot specify more than one Default (Unnamed) Graph in a TriG file", next);
                }
            }

            //Is there a discardable Equals token?
            if (next.TokenType == Token.EQUALS)
            {
                next = context.Tokens.Dequeue();
            }

            //Should the see a Left Curly Bracket
            if (next.TokenType == Token.LEFTCURLYBRACKET)
            {
                //Check that the Graph isn't empty i.e. the next token is not a } to close the Graph
                next = context.Tokens.Peek();
                if (next.TokenType == Token.RIGHTCURLYBRACKET)
                {
                    //Empty Graph so just discard the }
                    context.Tokens.Dequeue();
                }
                else
                {
                    //Parse Graph Contents
                    this.TryParseTriples(context, graphUri);
                }
            }
            else
            {
                throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a Left Curly Bracket to start a Graph", next);
            }

            //May optionally end with a Dot Token
            next = context.Tokens.Peek();
            if (next.TokenType == Token.DOT)
            {
                //Discard
                context.Tokens.Dequeue();
            }
        }
Пример #9
0
        private void TryParseTriples(TriGParserContext context, Uri graphUri)
        {
            do
            {
                //Try to get the Subject
                IToken subj = context.Tokens.Dequeue();
                INode  subjNode;

                //Turn the Subject Token into a Node
                switch (subj.TokenType)
                {
                case Token.COMMENT:
                    //Discard and continue
                    continue;

                case Token.QNAME:
                case Token.URI:
                    subjNode = ParserHelper.TryResolveUri(context, subj);
                    break;

                case Token.BLANKNODEWITHID:
                    //Blank Node with ID
                    subjNode = context.Handler.CreateBlankNode(subj.Value.Substring(2));
                    break;

                case Token.LEFTSQBRACKET:
                    //Blank Node
                    IToken next = context.Tokens.Peek();
                    if (next.TokenType == Token.RIGHTSQBRACKET)
                    {
                        //Anonymous Blank Node
                        context.Tokens.Dequeue();
                        subjNode = context.Handler.CreateBlankNode();
                    }
                    else
                    {
                        //Blank Node Collection
                        subjNode = context.Handler.CreateBlankNode();

                        //Do an extra call to TryParsePredicateObjectList to parse the Blank Node Collection
                        this.TryParsePredicateObjectList(context, graphUri, subjNode);
                    }
                    break;

                case Token.LEFTBRACKET:
                    //Collection

                    //Check whether an Empty Collection
                    next = context.Tokens.Peek();
                    if (next.TokenType == Token.RIGHTBRACKET)
                    {
                        //Empty Collection
                        context.Tokens.Dequeue();
                        subjNode = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil));
                    }
                    else
                    {
                        //Collection
                        subjNode = context.Handler.CreateBlankNode();
                        this.TryParseCollection(context, graphUri, subjNode);
                    }
                    break;

                case Token.EOF:
                    throw ParserHelper.Error("Unexpected End of File while trying to parse Triples", subj);

                default:
                    //Unexpected Token
                    throw ParserHelper.Error("Unexpected Token '" + subj.GetType().ToString() + "' encountered, expected a URI/QName/Blank Node as the Subject of a Triple", subj);
                }

                //Parse the Predicate Object List
                this.TryParsePredicateObjectList(context, graphUri, subjNode);

                //Expect a Dot to Terminate
                if (context.Tokens.LastTokenType != Token.DOT && context.Tokens.LastTokenType != Token.RIGHTCURLYBRACKET)
                {
                    //We only do this if we haven't returned because we already hit the Dot Token/Right Curly Bracket
                    IToken dot = context.Tokens.Dequeue();
                    if (dot.TokenType != Token.DOT && dot.TokenType != Token.RIGHTCURLYBRACKET)
                    {
                        throw ParserHelper.Error("Unexpected Token '" + dot.GetType().ToString() + "' encountered, expected a Dot (Line Terminator) Token to terminate Triples", dot);
                    }
                }

                //If we already hit the Right Curly Bracket return
                if (context.Tokens.LastTokenType == Token.RIGHTCURLYBRACKET)
                {
                    return;
                }
            } while (context.Tokens.Peek().TokenType != Token.RIGHTCURLYBRACKET);

            //Discard the ending Right Curly Bracket
            context.Tokens.Dequeue();
        }
Пример #10
0
        /// <summary>
        /// Parser method which parses Json Objects reprsenting Object Nodes
        /// </summary>
        /// <param name="context">Parser Context</param>
        /// <param name="subj">Subject of Triples which comes from the Great-Grandparent Json Object</param>
        /// <param name="pred">Predicate of Triples which comes form the Grandparent Json Object</param>
        private void ParseObject(JsonParserContext context, INode subj, INode pred)
        {
            String token, nodeValue, nodeType, nodeLang, nodeDatatype;

            nodeValue = nodeType = nodeLang = nodeDatatype = null;

            PositionInfo startPos = context.CurrentPosition;

            if (context.Input.Read())
            {
                if (context.Input.TokenType == JsonToken.StartObject)
                {
                    context.Input.Read();
                    while (context.Input.TokenType != JsonToken.EndObject)
                    {
                        if (context.Input.TokenType == JsonToken.PropertyName)
                        {
                            token = context.Input.Value.ToString().ToLower();

                            //Check that we get a Property Value as a String
                            context.Input.Read();
                            if (context.Input.TokenType != JsonToken.String)
                            {
                                throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Value describing one of the properties of an Object Node", startPos);
                            }

                            //Extract the Information from the Object
                            if (token.Equals("value"))
                            {
                                nodeValue = context.Input.Value.ToString();
                            }
                            else if (token.Equals("type"))
                            {
                                nodeType = context.Input.Value.ToString().ToLower();
                            }
                            else if (token.Equals("lang") || token.Equals("xml:lang"))
                            {
                                if (nodeLang == null && nodeDatatype == null)
                                {
                                    nodeLang = context.Input.Value.ToString();
                                }
                                else
                                {
                                    throw Error(context, "Unexpected Language Property specified for an Object Node where a Language or Datatype has already been specified", startPos);
                                }
                            }
                            else if (token.Equals("datatype"))
                            {
                                if (nodeDatatype == null && nodeLang == null)
                                {
                                    nodeDatatype = context.Input.Value.ToString();
                                }
                                else
                                {
                                    throw Error(context, "Unexpected Datatype Property specified for an Object Node where a Language or Datatype has already been specified", startPos);
                                }
                            }
                            else
                            {
                                throw Error(context, "Unexpected Property '" + token + "' specified for an Object Node, only 'value', 'type', 'lang' and 'datatype' are valid properties", startPos);
                            }
                        }
                        else
                        {
                            throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Name describing one of the properties of an Object Node", startPos);
                        }

                        context.Input.Read();
                    }

                    //Validate the Information
                    if (nodeType == null)
                    {
                        throw Error(context, "Cannot parse an Object Node from the JSON where no 'type' property was specified in the JSON Object representing the Node", startPos);
                    }
                    if (nodeValue == null)
                    {
                        throw Error(context, "Cannot parse an Object Node from the JSON where no 'value' property was specified in the JSON Object representing the Node", startPos);
                    }

                    //Turn this information into a Node
                    INode obj;
                    if (nodeType.Equals("uri"))
                    {
                        obj = context.Handler.CreateUriNode(UriFactory.Create(nodeValue));
                    }
                    else if (nodeType.Equals("bnode"))
                    {
                        obj = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.IndexOf(':') + 1));
                    }
                    else if (nodeType.Equals("literal"))
                    {
                        if (nodeLang != null)
                        {
                            obj = context.Handler.CreateLiteralNode(nodeValue, nodeLang);
                        }
                        else if (nodeDatatype != null)
                        {
                            obj = context.Handler.CreateLiteralNode(nodeValue, UriFactory.Create(nodeDatatype));
                        }
                        else
                        {
                            obj = context.Handler.CreateLiteralNode(nodeValue);
                        }
                    }
                    else
                    {
                        throw Error(context, "Cannot parse an Object Node from the JSON where the 'type' property is not set to one of the permitted values 'uri', 'bnode' or 'literal' in the JSON Object representing the Node", startPos);
                    }

                    //Assert as a Triple
                    if (!context.Handler.HandleTriple(new Triple(subj, pred, obj)))
                    {
                        ParserHelper.Stop();
                    }
                }
            }
            else
            {
                throw Error(context, "Unexpected End of Input while trying to parse an Object Node from the JSON", startPos);
            }
        }
Пример #11
0
        private void Parse(TriGParserContext context)
        {
            try
            {
                context.Handler.StartRdf();

                //Expect a BOF Token
                IToken first = context.Tokens.Dequeue();
                if (first.TokenType != Token.BOF)
                {
                    throw ParserHelper.Error("Unexpected Token '" + first.GetType().ToString() + "' encountered, expected a BOF Token", first);
                }

                //Expect either a Directive or a Graph
                IToken next;
                do
                {
                    next = context.Tokens.Peek();
                    switch (next.TokenType)
                    {
                    case Token.COMMENT:
                        //Discard
                        context.Tokens.Dequeue();
                        break;

                    case Token.EOF:
                        //End of File
                        context.Tokens.Dequeue();
                        break;

                    case Token.BASEDIRECTIVE:
                    case Token.PREFIXDIRECTIVE:
                        //Parse a Directive
                        this.TryParseDirective(context);
                        break;

                    case Token.QNAME:
                    case Token.URI:
                    case Token.LEFTCURLYBRACKET:
                        //Parse a Graph
                        this.TryParseGraph(context);
                        break;

                    default:
                        throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next);
                    }
                } while (next.TokenType != Token.EOF);

                context.Handler.EndRdf(true);
            }
            catch (RdfParsingTerminatedException)
            {
                context.Handler.EndRdf(true);
                //Discard this - it justs means the Handler told us to stop
            }
            catch
            {
                context.Handler.EndRdf(false);
                throw;
            }
        }
Пример #12
0
        private void TryParseResultRow(TokenisingResultParserContext context)
        {
            IToken next = context.Tokens.Peek();

            if (next.TokenType == Token.EOF)
            {
                context.Tokens.Dequeue();
                return;
            }

            bool         allowEOL = true, expectTab = false;
            int          v      = 0;
            SparqlResult result = new SparqlResult();

            while (true)
            {
                next = context.Tokens.Dequeue();
                switch (next.TokenType)
                {
                case Token.URI:
                    if (expectTab)
                    {
                        throw ParserHelper.Error("Unexpected URI, expected a Tab between RDF Terms", next);
                    }
                    if (v >= context.Variables.Count)
                    {
                        throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                    }
                    INode uri = ParserHelper.TryResolveUri(context, next);
                    result.SetValue(context.Variables[v], uri);
                    v++;
                    allowEOL  = true;
                    expectTab = true;
                    break;

                case Token.BLANKNODEWITHID:
                    if (expectTab)
                    {
                        throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next);
                    }
                    if (v >= context.Variables.Count)
                    {
                        throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                    }
                    INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2));
                    result.SetValue(context.Variables[v], blank);
                    v++;
                    allowEOL  = true;
                    expectTab = true;
                    break;

                case Token.LITERAL:
                case Token.LONGLITERAL:
                case Token.PLAINLITERAL:
                    if (expectTab)
                    {
                        throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next);
                    }
                    if (v >= context.Variables.Count)
                    {
                        throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                    }
                    INode lit = this.TryParseLiteral(context, next);
                    result.SetValue(context.Variables[v], lit);
                    v++;
                    allowEOL  = true;
                    expectTab = true;
                    break;

                case Token.EOL:
                    if (allowEOL)
                    {
                        break;
                    }
                    else
                    {
                        if (v == context.Variables.Count - 1)
                        {
                            //If this is the last expected term then this must be an empty term
                            v++;
                            break;
                        }
                        throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next);
                    }

                case Token.TAB:
                    if (!expectTab)
                    {
                        //This is an empty field
                        if (v >= context.Variables.Count)
                        {
                            throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next);
                        }
                        v++;
                    }
                    expectTab = false;
                    allowEOL  = false;
                    break;

                case Token.EOF:
                    if (!allowEOL)
                    {
                        throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next);
                    }
                    break;

                default:
                    throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next);
                }

                //Stop when we've hit the End of the Line/File
                if (next.TokenType == Token.EOL || next.TokenType == Token.EOF)
                {
                    break;
                }
            }

            if (!context.Handler.HandleResult(result))
            {
                ParserHelper.Stop();
            }
        }
Пример #13
0
        /// <summary>
        /// Tries to parse directives.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="directive"></param>
        /// <remarks>
        /// This overload is needed because in some cases we may dequeue a token before we know it is a directive.
        /// </remarks>
        private void TryParseDirective(TriGParserContext context, IToken directive)
        {
            // See what type of directive it is
            if (directive.TokenType == Token.BASEDIRECTIVE)
            {
                IToken baseUri = context.Tokens.Dequeue();
                if (baseUri.TokenType == Token.URI)
                {
                    try
                    {
                        Uri newBase = new Uri(Tools.ResolveUri(baseUri.Value, context.BaseUri.ToSafeString()));
                        context.BaseUri = newBase;
                        RaiseWarning("The @base directive is not valid in all versions of the TriG specification, your data may not be compatible with some older tools which do not support this version of TriG");
                        if (!context.Handler.HandleBaseUri(newBase))
                        {
                            ParserHelper.Stop();
                        }
                    }
                    catch (UriFormatException)
                    {
                        throw ParserHelper.Error("The URI '" + baseUri.Value + "' given for the Base URI  is not a valid URI", baseUri);
                    }
                }
                else
                {
                    throw ParserHelper.Error("Unexpected Token '" + baseUri.GetType().ToString() + "' encountered, expected a URI Token after a @base directive", baseUri);
                }
            }
            else if (directive.TokenType == Token.PREFIXDIRECTIVE)
            {
                // Prefix Directive
                IToken prefix = context.Tokens.Dequeue();
                if (prefix.TokenType == Token.PREFIX)
                {
                    IToken uri = context.Tokens.Dequeue();
                    if (uri.TokenType == Token.URI)
                    {
                        // Ensure the Uri is absolute
                        try
                        {
                            Uri    u   = new Uri(Tools.ResolveUri(uri.Value, context.BaseUri.ToSafeString()));
                            String pre = (prefix.Value.Equals(":")) ? String.Empty : prefix.Value.Substring(0, prefix.Value.Length - 1);
                            context.Namespaces.AddNamespace(pre, u);
                            if (!context.Handler.HandleNamespace(pre, u))
                            {
                                ParserHelper.Stop();
                            }
                        }
                        catch (UriFormatException)
                        {
                            throw ParserHelper.Error("The URI '" + uri.Value + "' given for the prefix '" + prefix.Value + "' is not a valid URI", uri);
                        }
                    }
                    else
                    {
                        throw ParserHelper.Error("Unexpected Token '" + prefix.GetType().ToString() + "' encountered, expected a URI Token after a Prefix Token", uri);
                    }
                }
                else
                {
                    throw ParserHelper.Error("Unexpected Token '" + prefix.GetType().ToString() + "' encountered, expected a Prefix Token after a Prefix Directive Token", prefix);
                }
            }
            else
            {
                throw ParserHelper.Error("Unexpected Token '" + directive.GetType().ToString() + "' encountered, expected a Base/Prefix Directive Token", directive);
            }

            // Expect a DOT to Terminate
            IToken dot = context.Tokens.Dequeue();

            if (dot.TokenType != Token.DOT)
            {
                throw ParserHelper.Error("Unexpected Token '" + dot.GetType().ToString() + "' encountered, expected a Dot (Line Terminator) Token to terminate a Base/Prefix Directive", dot);
            }
        }
Пример #14
0
        private void Parse(TriGParserContext context)
        {
            try
            {
                context.Handler.StartRdf();

                // Expect a BOF Token
                IToken first = context.Tokens.Dequeue();
                if (first.TokenType != Token.BOF)
                {
                    throw ParserHelper.Error("Unexpected Token '" + first.GetType().ToString() + "' encountered, expected a BOF Token", first);
                }

                // Expect either a Directive or a Graph
                IToken next;
                do
                {
                    next = context.Tokens.Peek();
                    switch (next.TokenType)
                    {
                    case Token.COMMENT:
                        // Discard
                        context.Tokens.Dequeue();
                        break;

                    case Token.EOF:
                        // End of File
                        context.Tokens.Dequeue();
                        break;

                    case Token.BASEDIRECTIVE:
                    case Token.PREFIXDIRECTIVE:
                        // Parse a Directive
                        TryParseDirective(context);
                        break;

                    case Token.QNAME:
                    case Token.URI:
                    case Token.LEFTCURLYBRACKET:
                        // Parse a Graph

                        if (context.Syntax != TriGSyntax.Original)
                        {
                            // We must take care here because @prefix and @base directives may be Graph scoped so anything visible currently
                            // remains visible and must be restored afterwards but anything inside the Graph is not visible outside of it
                            Uri extBase            = context.BaseUri;
                            INamespaceMapper nsmap = new NamespaceMapper(context.Namespaces);

                            TryParseGraph(context);

                            // After we parse the Graph restore the state
                            if (!context.Handler.HandleBaseUri(extBase))
                            {
                                ParserHelper.Stop();
                            }
                            context.BaseUri = extBase;
                            context.Namespaces.Clear();
                            foreach (String prefix in nsmap.Prefixes)
                            {
                                if (!context.Handler.HandleNamespace(prefix, nsmap.GetNamespaceUri(prefix)))
                                {
                                    ParserHelper.Stop();
                                }
                            }
                            context.Namespaces.Import(nsmap);
                        }
                        else
                        {
                            // With the old syntax declarations are file scoped so no need to worry about graph scoping
                            TryParseGraph(context);
                        }
                        break;

                    default:
                        throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next);
                    }
                } while (next.TokenType != Token.EOF);

                context.Handler.EndRdf(true);
            }
            catch (RdfParsingTerminatedException)
            {
                context.Handler.EndRdf(true);
                // Discard this - it justs means the Handler told us to stop
            }
            catch
            {
                context.Handler.EndRdf(false);
                throw;
            }
        }
Пример #15
0
        private Uri TryParseContext(ITokenQueue tokens)
        {
            IToken next = tokens.Dequeue();

            if (next.TokenType == Token.DOT)
            {
                return(null);
            }
            else
            {
                INode context;
                switch (next.TokenType)
                {
                case Token.BLANKNODEWITHID:
                    context = new BlankNode(null, next.Value.Substring(2));
                    break;

                case Token.URI:
                    context = new UriNode(null, UriFactory.Create(next.Value));
                    break;

                case Token.LITERAL:
                    //Check for Datatype/Language
                    IToken temp = tokens.Peek();
                    if (temp.TokenType == Token.LANGSPEC)
                    {
                        tokens.Dequeue();
                        context = new LiteralNode(null, next.Value, temp.Value);
                    }
                    else if (temp.TokenType == Token.DATATYPE)
                    {
                        tokens.Dequeue();
                        context = new LiteralNode(null, next.Value, UriFactory.Create(temp.Value.Substring(1, temp.Value.Length - 2)));
                    }
                    else
                    {
                        context = new LiteralNode(null, next.Value);
                    }
                    break;

                default:
                    throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a Blank Node/Literal/URI as the Context of the Triple", next);
                }

                //Ensure we then see a . to terminate the Quad
                next = tokens.Dequeue();
                if (next.TokenType != Token.DOT)
                {
                    throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a Dot Token (Line Terminator) to terminate a Triple", next);
                }

                //Finally return the Context URI
                if (context.NodeType == NodeType.Uri)
                {
                    return(((IUriNode)context).Uri);
                }
                else if (context.NodeType == NodeType.Blank)
                {
                    return(UriFactory.Create("nquads:bnode:" + context.GetHashCode()));
                }
                else if (context.NodeType == NodeType.Literal)
                {
                    return(UriFactory.Create("nquads:literal:" + context.GetHashCode()));
                }
                else
                {
                    throw ParserHelper.Error("Cannot turn a Node of type '" + context.GetType().ToString() + "' into a Context URI for a Triple", next);
                }
            }
        }
Пример #16
0
        private void TryParseTriple(XmlNode tripleEl, IRdfHandler handler, Uri graphUri)
        {
            //Verify Node Name
            if (!tripleEl.Name.Equals("triple"))
            {
                throw new RdfParseException("Unexpected Element <" + tripleEl.Name + "> encountered, only an optional <uri> element followed by zero/more <triple> elements are permitted within a <graph> element");
            }
            //Verify number of Child Nodes
            if (!tripleEl.HasChildNodes)
            {
                throw new RdfParseException("<triple> element has no child nodes - 3 child nodes are expected");
            }
            if (tripleEl.ChildNodes.Count < 3)
            {
                throw new RdfParseException("<triple> element has too few child nodes (" + tripleEl.ChildNodes.Count + ") - 3 child nodes are expected");
            }
            if (tripleEl.ChildNodes.Count > 3)
            {
                throw new RdfParseException("<triple> element has too many child nodes (" + tripleEl.ChildNodes.Count + ") - 3 child nodes are expected");
            }

            //Get the 3 Child Nodes
            XmlNode subjEl, predEl, objEl;

            subjEl = tripleEl.ChildNodes[0];
            predEl = tripleEl.ChildNodes[1];
            objEl  = tripleEl.ChildNodes[2];

            //Parse XML Nodes into RDF Nodes
            INode subj, pred, obj;

            if (subjEl.Name.Equals("uri"))
            {
                subj = handler.CreateUriNode(UriFactory.Create(subjEl.InnerText));
            }
            else if (subjEl.Name.Equals("id"))
            {
                subj = handler.CreateBlankNode(subjEl.InnerText);
            }
            else
            {
                throw Error("Unexpected element <" + subjEl.Name + "> encountered, expected a <id>/<uri> element as the Subject of a Triple", subjEl);
            }

            if (predEl.Name.Equals("uri"))
            {
                pred = handler.CreateUriNode(UriFactory.Create(predEl.InnerText));
            }
            else
            {
                throw Error("Unexpected element <" + predEl.Name + "> encountered, expected a <uri> element as the Predicate of a Triple", subjEl);
            }

            if (objEl.Name.Equals("uri"))
            {
                obj = handler.CreateUriNode(UriFactory.Create(objEl.InnerText));
            }
            else if (objEl.Name.Equals("id"))
            {
                obj = handler.CreateBlankNode(objEl.InnerText);
            }
            else if (objEl.Name.Equals("plainLiteral"))
            {
                if (objEl.Attributes.GetNamedItem("xml:lang") != null)
                {
                    obj = handler.CreateLiteralNode(objEl.InnerText, objEl.Attributes["xml:lang"].Value);
                }
                else
                {
                    obj = handler.CreateLiteralNode(objEl.InnerText);
                }
            }
            else if (objEl.Name.Equals("typedLiteral"))
            {
                if (objEl.Attributes.GetNamedItem("datatype") != null)
                {
                    Uri dtUri = UriFactory.Create(objEl.Attributes["datatype"].Value);
                    if (objEl.FirstChild.NodeType == XmlNodeType.Text)
                    {
                        obj = handler.CreateLiteralNode(objEl.InnerText, dtUri);
                    }
                    else if (objEl.FirstChild.NodeType == XmlNodeType.CDATA)
                    {
                        obj = handler.CreateLiteralNode(objEl.FirstChild.InnerXml, dtUri);
                    }
                    else
                    {
                        obj = handler.CreateLiteralNode(objEl.InnerText, dtUri);
                    }
                }
                else
                {
                    throw Error("<typedLiteral> element does not have the required datatype attribute", objEl);
                }
            }
            else
            {
                throw Error("Unexpected element <" + objEl.Name + "> encountered, expected a <id>/<uri>/<plainLiteral>/<typedLiteral> element as the Object of a Triple", subjEl);
            }

            //Assert the resulting Triple
            if (!handler.HandleTriple(new Triple(subj, pred, obj, graphUri)))
            {
                ParserHelper.Stop();
            }
            ;
        }