/// <summary> /// Generates the Turtle Syntax for the Graph /// </summary> private void GenerateOutput(CompressingTurtleWriterContext context) { //Create the Header //Base Directive if (context.Graph.BaseUri != null) { context.Output.WriteLine("@base <" + context.UriFormatter.FormatUri(context.Graph.BaseUri) + ">."); context.Output.WriteLine(); } //Prefix Directives foreach (String prefix in context.Graph.NamespaceMap.Prefixes) { if (TurtleSpecsHelper.IsValidQName(prefix + ":")) { if (!prefix.Equals(String.Empty)) { context.Output.WriteLine("@prefix " + prefix + ": <" + context.UriFormatter.FormatUri(context.Graph.NamespaceMap.GetNamespaceUri(prefix)) + ">."); } else { context.Output.WriteLine("@prefix : <" + context.UriFormatter.FormatUri(context.Graph.NamespaceMap.GetNamespaceUri(String.Empty)) + ">."); } } } context.Output.WriteLine(); //Decide on the Write Mode to use bool hiSpeed = false; double subjNodes = context.Graph.Triples.SubjectNodes.Count(); double triples = context.Graph.Triples.Count; if ((subjNodes / triples) > 0.75) { hiSpeed = true; } if (context.CompressionLevel == WriterCompressionLevel.None || (hiSpeed && context.HighSpeedModePermitted)) { this.RaiseWarning("High Speed Write Mode in use - minimal syntax compression will be used"); context.CompressionLevel = WriterCompressionLevel.Minimal; context.NodeFormatter = new UncompressedTurtleFormatter(); foreach (Triple t in context.Graph.Triples) { context.Output.WriteLine(this.GenerateTripleOutput(context, t)); } } else { if (context.CompressionLevel >= WriterCompressionLevel.More) { WriterHelper.FindCollections(context); } //Get the Triples as a Sorted List List <Triple> ts = context.Graph.Triples.Where(t => !context.TriplesDone.Contains(t)).ToList(); ts.Sort(new FullTripleComparer(new FastNodeComparer())); //Variables we need to track our writing INode lastSubj, lastPred; lastSubj = lastPred = null; int subjIndent = 0, predIndent = 0; String temp; for (int i = 0; i < ts.Count; i++) { Triple t = ts[i]; if (lastSubj == null || !t.Subject.Equals(lastSubj)) { //Terminate previous Triples if (lastSubj != null) { context.Output.WriteLine("."); } //Start a new set of Triples temp = this.GenerateNodeOutput(context, t.Subject, TripleSegment.Subject, 0); context.Output.Write(temp); context.Output.Write(" "); if (temp.Contains('\n')) { subjIndent = temp.Split('\n').Last().Length + 1; } else { subjIndent = temp.Length + 1; } lastSubj = t.Subject; //Write the first Predicate temp = this.GenerateNodeOutput(context, t.Predicate, TripleSegment.Predicate, subjIndent); context.Output.Write(temp); context.Output.Write(" "); predIndent = temp.Length + 1; lastPred = t.Predicate; } else if (lastPred == null || !t.Predicate.Equals(lastPred)) { //Terminate previous Predicate Object list context.Output.WriteLine(";"); if (context.PrettyPrint) { context.Output.Write(new String(' ', subjIndent)); } //Write the next Predicate temp = this.GenerateNodeOutput(context, t.Predicate, TripleSegment.Predicate, subjIndent); context.Output.Write(temp); context.Output.Write(" "); predIndent = temp.Length + 1; lastPred = t.Predicate; } else { //Continue Object List context.Output.WriteLine(","); if (context.PrettyPrint) { context.Output.Write(new String(' ', subjIndent + predIndent)); } } //Write the Object context.Output.Write(this.GenerateNodeOutput(context, t.Object, TripleSegment.Object, subjIndent + predIndent)); } //Terminate Triples if (ts.Count > 0) { context.Output.WriteLine("."); } return; } }
/// <summary> /// Internal method which generates the RDF/Json Output for a Graph /// </summary> /// <param name="context">Writer Context</param> private void GenerateOutput(RdfXmlWriterContext context) { context.UseDtd = this._useDTD; //Create required variables int nextNamespaceID = 0; List <String> tempNamespaces = new List <String>(); //Always force RDF Namespace to be correctly defined context.Graph.NamespaceMap.AddNamespace("rdf", new Uri(NamespaceMapper.RDF)); //Create an XML Document XmlDocument doc = new XmlDocument(); XmlDeclaration decl = doc.CreateXmlDeclaration("1.0", "UTF-8", null); doc.AppendChild(decl); //Create the DOCTYPE declaration and the rdf:RDF element StringBuilder entities = new StringBuilder(); XmlElement rdf = doc.CreateElement("rdf:RDF", NamespaceMapper.RDF); if (context.Graph.BaseUri != null) { XmlAttribute baseUri = doc.CreateAttribute("xml:base"); baseUri.Value = Uri.EscapeUriString(context.Graph.BaseUri.ToString()); rdf.Attributes.Append(baseUri); } XmlAttribute ns; String uri; entities.Append('\n'); foreach (String prefix in context.Graph.NamespaceMap.Prefixes) { uri = context.Graph.NamespaceMap.GetNamespaceUri(prefix).ToString(); if (!prefix.Equals(String.Empty)) { entities.AppendLine("\t<!ENTITY " + prefix + " '" + uri + "'>"); ns = doc.CreateAttribute("xmlns:" + prefix); ns.Value = Uri.EscapeUriString(uri.Replace("'", "'")); } else { ns = doc.CreateAttribute("xmlns"); ns.Value = Uri.EscapeUriString(uri); } rdf.Attributes.Append(ns); } if (context.UseDtd) { XmlDocumentType doctype = doc.CreateDocumentType("rdf:RDF", null, null, entities.ToString()); doc.AppendChild(doctype); } doc.AppendChild(rdf); //Find the Collections if (this._compressionLevel >= WriterCompressionLevel.More) { WriterHelper.FindCollections(context); } //Find the Type References Dictionary <INode, String> typerefs = this.FindTypeReferences(context, ref nextNamespaceID, tempNamespaces, doc); //Get the Triples as a Sorted List List <Triple> ts = context.Graph.Triples.Where(t => !context.TriplesDone.Contains(t)).ToList(); ts.Sort(); //Variables we need to track our writing INode lastSubj, lastPred; lastSubj = lastPred = null; XmlElement subj, pred; //Initialise stuff to keep the compiler happy subj = doc.CreateElement("rdf:Description", NamespaceMapper.RDF); pred = doc.CreateElement("temp"); for (int i = 0; i < ts.Count; i++) { Triple t = ts[i]; if (context.TriplesDone.Contains(t)) { continue; //Skip if already done } if (lastSubj == null || !t.Subject.Equals(lastSubj)) { //Start a new set of Triples //Validate Subject //Use a Type Reference if applicable if (typerefs.ContainsKey(t.Subject)) { String tref = typerefs[t.Subject]; String tprefix; if (tref.StartsWith(":")) { tprefix = String.Empty; } else if (tref.Contains(":")) { tprefix = tref.Substring(0, tref.IndexOf(':')); } else { tprefix = String.Empty; } subj = doc.CreateElement(tref, context.Graph.NamespaceMap.GetNamespaceUri(tprefix).ToString()); } else { subj = doc.CreateElement("rdf:Description", NamespaceMapper.RDF); } //Write out the Subject doc.DocumentElement.AppendChild(subj); lastSubj = t.Subject; //Apply appropriate attributes switch (t.Subject.NodeType) { case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: throw new RdfOutputException(WriterErrorMessages.LiteralSubjectsUnserializable("RDF/XML")); case NodeType.Blank: if (context.Collections.ContainsKey(t.Subject)) { this.GenerateCollectionOutput(context, t.Subject, subj, ref nextNamespaceID, tempNamespaces, doc); } else { XmlAttribute nodeID = doc.CreateAttribute("rdf:nodeID", NamespaceMapper.RDF); nodeID.Value = ((IBlankNode)t.Subject).InternalID; subj.Attributes.Append(nodeID); } break; case NodeType.Uri: this.GenerateUriOutput(context, (IUriNode)t.Subject, "rdf:about", tempNamespaces, subj, doc); break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } //Write the Predicate pred = this.GeneratePredicateNode(context, t.Predicate, ref nextNamespaceID, tempNamespaces, doc, subj); subj.AppendChild(pred); lastPred = t.Predicate; } else if (lastPred == null || !t.Predicate.Equals(lastPred)) { //Write the Predicate pred = this.GeneratePredicateNode(context, t.Predicate, ref nextNamespaceID, tempNamespaces, doc, subj); subj.AppendChild(pred); lastPred = t.Predicate; } //Write the Object //Create an Object for the Object switch (t.Object.NodeType) { case NodeType.Blank: if (pred.HasChildNodes || pred.HasAttributes) { //Require a new Predicate pred = this.GeneratePredicateNode(context, t.Predicate, ref nextNamespaceID, tempNamespaces, doc, subj); subj.AppendChild(pred); } if (context.Collections.ContainsKey(t.Object)) { //Output a Collection this.GenerateCollectionOutput(context, t.Object, pred, ref nextNamespaceID, tempNamespaces, doc); } else { //Terminate the Blank Node triple by adding a rdf:nodeID attribute XmlAttribute nodeID = doc.CreateAttribute("rdf:nodeID", NamespaceMapper.RDF); nodeID.Value = ((IBlankNode)t.Object).InternalID; pred.Attributes.Append(nodeID); } //Force a new Predicate after Blank Nodes lastPred = null; break; case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: ILiteralNode lit = (ILiteralNode)t.Object; if (pred.HasChildNodes || pred.HasAttributes) { //Require a new Predicate pred = this.GeneratePredicateNode(context, t.Predicate, ref nextNamespaceID, tempNamespaces, doc, subj); subj.AppendChild(pred); } this.GenerateLiteralOutput(context, lit, pred, doc); //Force a new Predicate Node after Literals lastPred = null; break; case NodeType.Uri: this.GenerateUriOutput(context, (IUriNode)t.Object, "rdf:resource", tempNamespaces, pred, doc); //Force a new Predicate Node after URIs lastPred = null; break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } context.TriplesDone.Add(t); } //Check we haven't failed to output any collections foreach (KeyValuePair <INode, OutputRdfCollection> pair in context.Collections) { if (!pair.Value.HasBeenWritten) { if (typerefs.ContainsKey(pair.Key)) { String tref = typerefs[pair.Key]; String tprefix; if (tref.StartsWith(":")) { tref = tref.Substring(1); tprefix = String.Empty; } else if (tref.Contains(":")) { tprefix = tref.Substring(0, tref.IndexOf(':')); } else { tprefix = String.Empty; } subj = doc.CreateElement(tref, context.Graph.NamespaceMap.GetNamespaceUri(tprefix).ToString()); doc.DocumentElement.AppendChild(subj); this.GenerateCollectionOutput(context, pair.Key, subj, ref nextNamespaceID, tempNamespaces, doc); } else { //Generate an rdf:Description Node with a rdf:nodeID on it XmlElement colNode = doc.CreateElement("rdf:Description"); XmlAttribute nodeID = doc.CreateAttribute("rdf:nodeID"); nodeID.Value = ((IBlankNode)pair.Key).InternalID; colNode.Attributes.Append(nodeID); doc.DocumentElement.AppendChild(colNode); this.GenerateCollectionOutput(context, pair.Key, colNode, ref nextNamespaceID, tempNamespaces, doc); //throw new RdfOutputException("Failed to output a Collection due to an unknown error"); } } } //Save to the Output Stream InternalXmlWriter writer = new InternalXmlWriter(); writer.Save(context.Output, doc); //Get rid of the Temporary Namespace foreach (String tempPrefix in tempNamespaces) { context.Graph.NamespaceMap.RemoveNamespace(tempPrefix); } }
/// <summary> /// Internal method which generates the RDF/Json Output for a Graph /// </summary> /// <param name="g">Graph to save</param> /// <param name="output">Stream to save to</param> private void GenerateOutput(IGraph g, TextWriter output) { // Always force RDF Namespace to be correctly defined g.NamespaceMap.Import(_defaultNamespaces); g.NamespaceMap.AddNamespace("rdf", UriFactory.Create(NamespaceMapper.RDF)); // Create our Writer Context and start the XML Document RdfXmlWriterContext context = new RdfXmlWriterContext(g, output); context.CompressionLevel = _compressionLevel; context.UseDtd = _useDTD; context.Writer.WriteStartDocument(); if (context.UseDtd) { // Create the DOCTYPE declaration StringBuilder entities = new StringBuilder(); String uri; entities.Append('\n'); foreach (String prefix in context.NamespaceMap.Prefixes) { uri = context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri; if (!uri.Equals(context.NamespaceMap.GetNamespaceUri(prefix).ToString())) { context.UseDtd = false; break; } if (!prefix.Equals(String.Empty)) { var escapedUri = WriterHelper.EncodeForXml(uri); entities.AppendLine("\t<!ENTITY " + prefix + " '" + escapedUri + "'>"); } } if (context.UseDtd) { context.Writer.WriteDocType("rdf:RDF", null, null, entities.ToString()); } } // Create the rdf:RDF element context.Writer.WriteStartElement("rdf", "RDF", NamespaceMapper.RDF); if (context.Graph.BaseUri != null) { context.Writer.WriteAttributeString("xml", "base", null, context.Graph.BaseUri.AbsoluteUri);//Uri.EscapeUriString(context.Graph.BaseUri.ToString())); } context.NamespaceMap.IncrementNesting(); foreach (String prefix in context.NamespaceMap.Prefixes) { if (prefix.Equals("rdf")) { continue; } if (!prefix.Equals(String.Empty)) { context.Writer.WriteStartAttribute("xmlns", prefix, null); // String nsRef = "&" + prefix + ";"; // context.Writer.WriteRaw(nsRef); // context.Writer.WriteEntityRef(prefix); context.Writer.WriteRaw(WriterHelper.EncodeForXml(context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri));//Uri.EscapeUriString(WriterHelper.EncodeForXml(context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri))); context.Writer.WriteEndAttribute(); } else { context.Writer.WriteStartAttribute("xmlns"); context.Writer.WriteRaw(WriterHelper.EncodeForXml(context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri));//Uri.EscapeUriString(WriterHelper.EncodeForXml(context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri))); context.Writer.WriteEndAttribute(); } } // Find the Collections and Type References if (context.CompressionLevel >= WriterCompressionLevel.More) { WriterHelper.FindCollections(context, CollectionSearchMode.ImplicitOnly); // WriterHelper.FindCollections(context, CollectionSearchMode.All); } Dictionary <INode, String> typerefs = FindTypeReferences(context); // Get the Triples as a Sorted List List <Triple> ts = context.Graph.Triples.Where(t => !context.TriplesDone.Contains(t)).ToList(); ts.Sort(new RdfXmlTripleComparer()); // Variables we need to track our writing INode lastSubj, lastPred, lastObj; lastSubj = lastPred = lastObj = null; for (int i = 0; i < ts.Count; i++) { Triple t = ts[i]; if (context.TriplesDone.Contains(t)) { continue; //Skip if already done } if (lastSubj == null || !t.Subject.Equals(lastSubj)) { // Start a new set of Triples if (lastSubj != null) { context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndElement(); } if (lastPred != null) { context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndElement(); } // Write out the Subject // Validate Subject // Use a Type Reference if applicable context.NamespaceMap.IncrementNesting(); if (typerefs.ContainsKey(t.Subject)) { String tref = typerefs[t.Subject]; if (tref.StartsWith(":")) { context.Writer.WriteStartElement(tref.Substring(1)); } else if (tref.Contains(":")) { context.Writer.WriteStartElement(tref.Substring(0, tref.IndexOf(':')), tref.Substring(tref.IndexOf(':') + 1), null); } else { context.Writer.WriteStartElement(tref); } } else { context.Writer.WriteStartElement("rdf", "Description", NamespaceMapper.RDF); } lastSubj = t.Subject; // Apply appropriate attributes switch (t.Subject.NodeType) { case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: throw new RdfOutputException(WriterErrorMessages.LiteralSubjectsUnserializable("RDF/XML")); case NodeType.Blank: if (context.Collections.ContainsKey(t.Subject)) { GenerateCollectionOutput(context, t.Subject); } else { context.Writer.WriteAttributeString("rdf", "nodeID", null, context.BlankNodeMapper.GetOutputID(((IBlankNode)t.Subject).InternalID)); } break; case NodeType.Uri: GenerateUriOutput(context, (IUriNode)t.Subject, "rdf:about"); break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } // Write the Predicate context.NamespaceMap.IncrementNesting(); GeneratePredicateNode(context, t.Predicate); lastPred = t.Predicate; lastObj = null; } else if (lastPred == null || !t.Predicate.Equals(lastPred)) { if (lastPred != null) { context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndElement(); } // Write the Predicate context.NamespaceMap.IncrementNesting(); GeneratePredicateNode(context, t.Predicate); lastPred = t.Predicate; lastObj = null; } // Write the Object if (lastObj != null) { // Terminate the previous Predicate Node context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndElement(); // Start a new Predicate Node context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndElement(); context.NamespaceMap.IncrementNesting(); GeneratePredicateNode(context, t.Predicate); } // Create an Object for the Object switch (t.Object.NodeType) { case NodeType.Blank: if (context.Collections.ContainsKey(t.Object)) { // Output a Collection GenerateCollectionOutput(context, t.Object); } else { // Terminate the Blank Node triple by adding a rdf:nodeID attribute context.Writer.WriteAttributeString("rdf", "nodeID", null, context.BlankNodeMapper.GetOutputID(((IBlankNode)t.Object).InternalID)); } break; case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: ILiteralNode lit = (ILiteralNode)t.Object; GenerateLiteralOutput(context, lit); break; case NodeType.Uri: GenerateUriOutput(context, (IUriNode)t.Object, "rdf:resource"); break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } lastObj = t.Object; // Force a new Predicate Node context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndElement(); lastPred = null; context.TriplesDone.Add(t); } // Check we haven't failed to output any collections foreach (KeyValuePair <INode, OutputRdfCollection> pair in context.Collections) { if (pair.Value.Triples.Count > 0) { if (typerefs.ContainsKey(pair.Key)) { String tref = typerefs[pair.Key]; context.NamespaceMap.IncrementNesting(); if (tref.StartsWith(":")) { context.Writer.WriteStartElement(tref.Substring(1)); } else if (tref.Contains(":")) { context.Writer.WriteStartElement(tref.Substring(0, tref.IndexOf(':')), tref.Substring(tref.IndexOf(':') + 1), null); } else { context.Writer.WriteStartElement(tref); } GenerateCollectionOutput(context, pair.Key); context.Writer.WriteEndElement(); } else { context.Writer.WriteStartElement("rdf", "Description", NamespaceMapper.RDF); context.Writer.WriteAttributeString("rdf", "nodeID", NamespaceMapper.RDF, context.BlankNodeMapper.GetOutputID(((IBlankNode)pair.Key).InternalID)); GenerateCollectionOutput(context, pair.Key); context.Writer.WriteEndElement(); // throw new RdfOutputException("Failed to output a Collection due to an unknown error"); } } } context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndDocument(); // Save to the Output Stream context.Writer.Flush(); }
public void WritingCollectionCompressionNamedListNodes3() { Graph g = new Graph(); INode data1 = g.CreateBlankNode(); g.Assert(data1, g.CreateUriNode(new Uri("http://property")), g.CreateLiteralNode("test1")); INode data2 = g.CreateBlankNode(); g.Assert(data2, g.CreateUriNode(new Uri("http://property")), g.CreateLiteralNode("test2")); INode listEntry1 = g.CreateUriNode(new Uri("http://test/1")); INode rdfFirst = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfListFirst)); INode rdfRest = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfListRest)); INode rdfNil = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfListNil)); g.Assert(listEntry1, rdfFirst, data1); g.Assert(listEntry1, rdfRest, rdfNil); INode listEntry2 = g.CreateUriNode(new Uri("http://test/2")); g.Assert(listEntry2, rdfFirst, data2); g.Assert(listEntry2, rdfRest, listEntry1); INode root = g.CreateUriNode(new Uri("http://root")); g.Assert(root, g.CreateUriNode(new Uri("http://list")), listEntry2); NTriplesFormatter formatter = new NTriplesFormatter(); _output.WriteLine("Original Graph"); foreach (Triple t in g.Triples) { _output.WriteLine(t.ToString(formatter)); } _output.WriteLine(""); var sw = new System.IO.StringWriter(); CompressingTurtleWriterContext context = new CompressingTurtleWriterContext(g, sw); WriterHelper.FindCollections(context); _output.WriteLine(sw.ToString()); _output.WriteLine(context.Collections.Count + " Collections Found"); _output.WriteLine(""); System.IO.StringWriter strWriter = new System.IO.StringWriter(); CompressingTurtleWriter writer = new CompressingTurtleWriter(); writer.CompressionLevel = WriterCompressionLevel.High; writer.Save(g, strWriter); _output.WriteLine("Compressed Turtle"); _output.WriteLine(strWriter.ToString()); _output.WriteLine(""); Graph h = new Graph(); TurtleParser parser = new TurtleParser(); StringParser.Parse(h, strWriter.ToString()); _output.WriteLine("Graph after Round Trip to Compressed Turtle"); foreach (Triple t in h.Triples) { _output.WriteLine(t.ToString(formatter)); } Assert.Equal(g, h); }
/// <summary> /// Internal method which generates the RDF/Json Output for a Graph. /// </summary> /// <param name="g">Graph to save.</param> /// <param name="output">Stream to save to.</param> private void GenerateOutput(IGraph g, TextWriter output) { // Always force RDF Namespace to be correctly defined g.NamespaceMap.Import(_defaultNamespaces); g.NamespaceMap.AddNamespace("rdf", UriFactory.Create(NamespaceMapper.RDF)); // Create our Writer Context and start the XML Document RdfXmlWriterContext context = new RdfXmlWriterContext(g, output); context.CompressionLevel = _compressionLevel; context.UseDtd = _useDTD; context.UseAttributes = _useAttributes; context.Writer.WriteStartDocument(); if (context.UseDtd) { // Create the DOCTYPE declaration StringBuilder entities = new StringBuilder(); String uri; entities.Append('\n'); foreach (String prefix in context.NamespaceMap.Prefixes) { uri = context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri; if (!uri.Equals(context.NamespaceMap.GetNamespaceUri(prefix).ToString())) { context.UseDtd = false; break; } if (!prefix.Equals(String.Empty)) { entities.AppendLine("\t<!ENTITY " + prefix + " '" + uri + "'>"); } } if (context.UseDtd) { context.Writer.WriteDocType("rdf:RDF", null, null, entities.ToString()); } } // Create the rdf:RDF element context.Writer.WriteStartElement("rdf", "RDF", NamespaceMapper.RDF); if (context.Graph.BaseUri != null) { context.Writer.WriteAttributeString("xml", "base", null, context.Graph.BaseUri.AbsoluteUri); } // Add all the existing Namespace Definitions here context.NamespaceMap.IncrementNesting(); foreach (String prefix in context.NamespaceMap.Prefixes) { if (prefix.Equals("rdf")) { continue; } if (!prefix.Equals(String.Empty)) { context.Writer.WriteStartAttribute("xmlns", prefix, null); context.Writer.WriteString(context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri);//Uri.EscapeUriString(context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri)); context.Writer.WriteEndAttribute(); } else { context.Writer.WriteStartAttribute("xmlns"); context.Writer.WriteString(context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri);//Uri.EscapeUriString(context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri)); context.Writer.WriteEndAttribute(); } } // Find the Collections and Type References if (context.CompressionLevel >= WriterCompressionLevel.More) { WriterHelper.FindCollections(context, CollectionSearchMode.All); } // Get the Triples as a Sorted List List <Triple> ts = context.Graph.Triples.Where(t => !context.TriplesDone.Contains(t)).ToList(); ts.Sort(new RdfXmlTripleComparer()); INode lastSubj = null; List <Triple> sameSubject = new List <Triple>(); for (int i = 0; i < ts.Count; i++) { // Find the first group of Triples with the same subject if (lastSubj == null) { // Start of new set of Triples with the same subject lastSubj = ts[i].Subject; sameSubject.Add(ts[i]); if (lastSubj.NodeType == NodeType.GraphLiteral) { throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); } else if (lastSubj.NodeType == NodeType.Variable) { throw new RdfOutputException(WriterErrorMessages.VariableNodesUnserializable("RDF/XML")); } } else { if (ts[i].Subject.Equals(lastSubj)) { // Still finding Triples with same subject sameSubject.Add(ts[i]); } else { // Found the end of current set of Triples with same subject GenerateSubjectOutput(context, sameSubject, true); // Reset so we'll start from a new subject on next iteration sameSubject.Clear(); lastSubj = null; i--; } } } // Ensure last set of Triples with same subject gets written if (sameSubject.Count > 0) { GenerateSubjectOutput(context, sameSubject, true); } // Take care of any collections that weren't yet written foreach (KeyValuePair <INode, OutputRdfCollection> kvp in context.Collections) { if (!kvp.Value.HasBeenWritten) { // Generate a rdf:Description node and then write the collection context.Writer.WriteStartElement("rdf", "Description", NamespaceMapper.RDF); if (kvp.Value.Triples.Count > 0 || !kvp.Value.IsExplicit) { context.Writer.WriteAttributeString("rdf", "nodeID", NamespaceMapper.RDF, context.BlankNodeMapper.GetOutputID(((IBlankNode)kvp.Key).InternalID)); } GenerateCollectionOutput(context, kvp.Key); context.Writer.WriteEndElement(); } } context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndDocument(); // Save to the Output Stream context.Writer.Flush(); }