/// <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="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 = 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.Replace("'", "'"); } else { ns = doc.CreateAttribute("xmlns"); ns.Value = 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); } }