private void GenerateTemporaryNamespace(RdfXmlWriterContext context, IUriNode u, ref int nextNamespaceID, List <String> tempNamespaceIDs, XmlDocument doc) { String uri = u.Uri.ToString(); String nsUri; if (uri.Contains("#")) { //Create a Hash Namespace Uri nsUri = uri.Substring(0, uri.LastIndexOf("#") + 1); } else { //Create a Slash Namespace Uri nsUri = uri.Substring(0, uri.LastIndexOf("/") + 1); } //Create a Temporary Namespace ID while (context.Graph.NamespaceMap.HasNamespace("ns" + nextNamespaceID)) { nextNamespaceID++; } String prefix = "ns" + nextNamespaceID; nextNamespaceID++; context.Graph.NamespaceMap.AddNamespace(prefix, new Uri(nsUri)); tempNamespaceIDs.Add(prefix); //Add to XML Document Element XmlAttribute ns = doc.CreateAttribute("xmlns:" + prefix, "http://www.w3.org/2000/xmlns/"); ns.Value = Uri.EscapeUriString(nsUri); doc.DocumentElement.Attributes.Append(ns); this.RaiseWarning("Created a Temporary Namespace '" + prefix + "' with URI '" + nsUri + "'"); }
private void GenerateCollectionItemOutput(RdfXmlWriterContext context, OutputRdfCollection c) { // Then output the elements of the Collection int toClose = c.Triples.Count; while (c.Triples.Count > 0) { Triple t = c.Triples[0]; c.Triples.RemoveAt(0); // rdf:first Node context.Writer.WriteStartElement("rdf", "first", NamespaceMapper.RDF); GenerateObjectOutput(context, t); context.TriplesDone.Add(t); context.Writer.WriteEndElement(); // rdf:rest Node context.Writer.WriteStartElement("rdf", "rest", NamespaceMapper.RDF); } // Terminate the list and close all the open rdf:rest elements context.Writer.WriteAttributeString("rdf", "resource", NamespaceMapper.RDF, RdfSpecsHelper.RdfListNil); for (int i = 0; i < toClose; i++) { context.Writer.WriteEndElement(); } }
private void GenerateUriOutput(RdfXmlWriterContext context, IUriNode u, String attribute) { // Get a Uri Reference if the Uri can be reduced UriRefType rtype; String uriref = this.GenerateUriRef(context, u.Uri, UriRefType.UriRef, out rtype); if (attribute.Contains(':')) { context.Writer.WriteStartAttribute(attribute.Substring(0, attribute.IndexOf(':')), attribute.Substring(attribute.IndexOf(':') + 1), NamespaceMapper.RDF); if (rtype == UriRefType.UriRef) { context.Writer.WriteRaw(WriterHelper.EncodeForXml(uriref));//Uri.EscapeUriString(WriterHelper.EncodeForXml(uriref))); } else { context.Writer.WriteString(uriref);//Uri.EscapeUriString(uriref)); } context.Writer.WriteEndAttribute(); } else { context.Writer.WriteStartAttribute(attribute); if (rtype == UriRefType.UriRef) { context.Writer.WriteRaw(WriterHelper.EncodeForXml(uriref));//Uri.EscapeUriString(WriterHelper.EncodeForXml(uriref))); } else { context.Writer.WriteString(uriref);//Uri.EscapeUriString(uriref)); } context.Writer.WriteEndAttribute(); } }
private void GenerateLiteralOutput(RdfXmlWriterContext context, ILiteralNode lit, XmlElement pred, XmlDocument doc) { pred.InnerText = WriterHelper.EncodeForXml(lit.Value); //pred.InnerText = XmlConvert.ToString(lit.Value); if (!lit.Language.Equals(String.Empty)) { XmlAttribute lang = doc.CreateAttribute("xml:lang"); lang.Value = lit.Language; pred.Attributes.Append(lang); } else if (lit.DataType != null) { if (RdfSpecsHelper.RdfXmlLiteral.Equals(lit.DataType.ToString())) { XmlAttribute parseType = doc.CreateAttribute("rdf:parseType"); parseType.Value = "Literal"; pred.Attributes.Append(parseType); pred.InnerText = String.Empty; XmlDocumentFragment fragment = doc.CreateDocumentFragment(); fragment.InnerXml = lit.Value; pred.AppendChild(fragment); } else { XmlAttribute dt = doc.CreateAttribute("rdf:datatype"); dt.Value = Uri.EscapeUriString(lit.DataType.ToString()); pred.Attributes.Append(dt); } } }
private void GenerateTemporaryNamespace(RdfXmlWriterContext context, IUriNode u, out String tempPrefix, out String tempUri) { String uri = u.Uri.AbsoluteUri; String nsUri; if (uri.Contains("#")) { // Create a Hash Namespace Uri nsUri = uri.Substring(0, uri.LastIndexOf("#") + 1); } else { // Create a Slash Namespace Uri nsUri = uri.Substring(0, uri.LastIndexOf("/") + 1); } // Create a Temporary Namespace ID // Can't use an ID if already in the Namespace Map either at top level (nesting == 0) or at the current nesting while (context.NamespaceMap.HasNamespace("ns" + context.NextNamespaceID) && (context.NamespaceMap.GetNestingLevel("ns" + context.NextNamespaceID) == 0 || context.NamespaceMap.GetNestingLevel("ns" + context.NextNamespaceID) == context.NamespaceMap.NestingLevel)) { context.NextNamespaceID++; } String prefix = "ns" + context.NextNamespaceID; context.NextNamespaceID++; context.NamespaceMap.AddNamespace(prefix, UriFactory.Create(nsUri)); tempPrefix = prefix; tempUri = nsUri; RaiseWarning("Created a Temporary Namespace '" + prefix + "' with URI '" + nsUri + "'"); }
private String GenerateUriRef(RdfXmlWriterContext context, Uri u, UriRefType type, out UriRefType outType) { String uriref, qname; if (context.NamespaceMap.ReduceToQName(u.ToString(), out qname) && RdfXmlSpecsHelper.IsValidQName(qname)) { //Reduced to QName OK uriref = qname; outType = UriRefType.QName; } else { //Just use the Uri uriref = u.ToString(); outType = UriRefType.Uri; } //Convert to a Uri Ref from a QName if required if (outType == UriRefType.QName && type == UriRefType.UriRef) { if (uriref.Contains(':') && !uriref.StartsWith(":")) { String prefix = uriref.Substring(0, uriref.IndexOf(':')); if (context.UseDtd && context.NamespaceMap.GetNestingLevel(prefix) == 0) { //Must have Use DTD enabled //Can only use entities for non-temporary Namespaces as Temporary Namespaces won't have Entities defined uriref = "&" + uriref.Replace(':', ';'); outType = UriRefType.UriRef; } else { uriref = context.NamespaceMap.GetNamespaceUri(prefix).ToString() + uriref.Substring(uriref.IndexOf(':') + 1); outType = UriRefType.Uri; } } else { if (context.NamespaceMap.HasNamespace(String.Empty)) { uriref = context.NamespaceMap.GetNamespaceUri(String.Empty).ToString() + uriref.Substring(1); outType = UriRefType.Uri; } else { String baseUri = context.Graph.BaseUri.ToString(); if (!baseUri.EndsWith("#")) { baseUri += "#"; } uriref = baseUri + uriref; outType = UriRefType.Uri; } } //outType = UriRefType.UriRef; } return(uriref); }
private void GeneratePredicateOutput(RdfXmlWriterContext context, Triple t) { context.NamespaceMap.IncrementNesting(); // Must ensure a URI predicate switch (t.Predicate.NodeType) { case NodeType.Blank: throw new RdfOutputException(WriterErrorMessages.BlankPredicatesUnserializable("RDF/XML")); case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: throw new RdfOutputException(WriterErrorMessages.LiteralPredicatesUnserializable("RDF/XML")); case NodeType.Variable: throw new RdfOutputException(WriterErrorMessages.VariableNodesUnserializable("RDF/XML")); } IUriNode p = (IUriNode)t.Predicate; // First generate the Predicate Node UriRefType outType; String uriref = GenerateUriRef(context, p.Uri, UriRefType.QName, out outType); String tempPrefix = null, tempUri = null; if (outType != UriRefType.QName) { // Need to generate a temporary namespace GenerateTemporaryNamespace(context, p, out tempPrefix, out tempUri); uriref = GenerateUriRef(context, p.Uri, UriRefType.QName, out outType); if (outType != UriRefType.QName) { throw new RdfOutputException(WriterErrorMessages.UnreducablePropertyURIUnserializable + " - '" + p.Uri + "'"); } } // Use the QName for the Node if (uriref.Contains(':')) { // Create an element in the appropriate namespace String ns = context.NamespaceMap.GetNamespaceUri(uriref.Substring(0, uriref.IndexOf(':'))).AbsoluteUri; context.Writer.WriteStartElement(uriref.Substring(0, uriref.IndexOf(':')), uriref.Substring(uriref.IndexOf(':') + 1), ns); } else { // Create an element in the default namespace context.Writer.WriteStartElement(uriref); } if (tempPrefix != null && tempUri != null) { context.Writer.WriteAttributeString("xmlns", tempPrefix, null, Uri.EscapeUriString(tempUri)); } // Then generate the Object Output GenerateObjectOutput(context, t); context.Writer.WriteEndElement(); context.NamespaceMap.DecrementNesting(); }
private String GenerateUriRef(RdfXmlWriterContext context, IUriNode u, UriRefType type, List <String> tempNamespaceIDs, out UriRefType outType) { String uriref, qname; if (context.Graph.NamespaceMap.ReduceToQName(u.Uri.ToString(), out qname)) { //Reduced to QName OK uriref = qname; outType = UriRefType.QName; } else { //Just use the Uri uriref = u.Uri.ToString(); outType = UriRefType.Uri; } //Convert to a Uri Ref from a QName if required if (outType == UriRefType.QName && type == UriRefType.UriRef) { if (uriref.Contains(':') && !uriref.StartsWith(":")) { String prefix = uriref.Substring(0, uriref.IndexOf(':')); if (context.UseDtd && !tempNamespaceIDs.Contains(prefix)) { //Must be using a DTD to use references of this form //Can only use entities for non-temporary Namespaces as Temporary Namespaces won't have Entities defined uriref = "&" + uriref.Replace(':', ';'); } else { uriref = context.Graph.NamespaceMap.GetNamespaceUri(prefix).ToString() + uriref.Substring(uriref.IndexOf(':') + 1); } } else { if (context.Graph.NamespaceMap.HasNamespace(String.Empty)) { uriref = context.Graph.NamespaceMap.GetNamespaceUri(String.Empty).ToString() + uriref.Substring(1); } else { String baseUri = context.Graph.BaseUri.ToString(); if (!baseUri.EndsWith("#")) { baseUri += "#"; } uriref = baseUri + uriref; } } outType = UriRefType.UriRef; } return(uriref); }
private Dictionary <INode, String> FindTypeReferences(RdfXmlWriterContext context) { // LINQ query to find all Triples which define the rdf:type of a Uri/BNode as a Uri IUriNode rdfType = context.Graph.CreateUriNode(UriFactory.Create(NamespaceMapper.RDF + "type")); IEnumerable <Triple> ts = from t in context.Graph.Triples where (t.Subject.NodeType == NodeType.Blank || t.Subject.NodeType == NodeType.Uri) && t.Predicate.Equals(rdfType) && t.Object.NodeType == NodeType.Uri && !context.TriplesDone.Contains(t) select t; Dictionary <INode, String> typerefs = new Dictionary <INode, string>(); foreach (Triple t in ts) { if (!typerefs.ContainsKey(t.Subject)) { String typeref; UriRefType rtype; typeref = this.GenerateUriRef(context, ((IUriNode)t.Object).Uri, UriRefType.QName, out rtype); if (rtype != UriRefType.QName) { // Generate a Temporary Namespace for the QName Type Reference String prefix, uri; this.GenerateTemporaryNamespace(context, (IUriNode)t.Object, out prefix, out uri); // Add to current XML Element context.Writer.WriteStartAttribute("xmlns", prefix, null); context.Writer.WriteRaw(Uri.EscapeUriString(WriterHelper.EncodeForXml(uri))); context.Writer.WriteEndAttribute(); typeref = this.GenerateUriRef(context, ((IUriNode)t.Object).Uri, UriRefType.QName, out rtype); if (rtype == UriRefType.QName) { // Got a QName Type Reference in the Temporary Namespace OK typerefs.Add(t.Subject, typeref); if (context.Graph.Triples.WithSubject(t.Subject).Count() > 1) { context.TriplesDone.Add(t); } } } else { // Got a QName Type Reference OK typerefs.Add(t.Subject, typeref); if (context.Graph.Triples.WithSubject(t.Subject).Count() > 1) { context.TriplesDone.Add(t); } } } } return(typerefs); }
private void GenerateUriOutput(RdfXmlWriterContext context, IUriNode u, String attribute, List <String> tempNamespaceIDs, XmlElement node, XmlDocument doc) { //Create an attribute XmlAttribute attr = doc.CreateAttribute(attribute, NamespaceMapper.RDF); //Get a Uri Reference if the Uri can be reduced UriRefType rtype; String uriref = this.GenerateUriRef(context, u, UriRefType.UriRef, tempNamespaceIDs, out rtype); attr.InnerXml = Uri.EscapeUriString(WriterHelper.EncodeForXml(uriref)); //Append the attribute node.Attributes.Append(attr); }
private Dictionary <INode, String> FindTypeReferences(RdfXmlWriterContext context, ref int nextNamespaceID, List <String> tempNamespaceIDs, XmlDocument doc) { //LINQ query to find all Triples which define the rdf:type of a Uri/BNode as a Uri IUriNode rdfType = context.Graph.CreateUriNode(new Uri(NamespaceMapper.RDF + "type")); IEnumerable <Triple> ts = from t in context.Graph.Triples where (t.Subject.NodeType == NodeType.Blank || t.Subject.NodeType == NodeType.Uri) && t.Predicate.Equals(rdfType) && t.Object.NodeType == NodeType.Uri && !context.TriplesDone.Contains(t) select t; Dictionary <INode, String> typerefs = new Dictionary <INode, string>(); foreach (Triple t in ts) { if (!typerefs.ContainsKey(t.Subject)) { String typeref; UriRefType rtype; typeref = this.GenerateUriRef(context, (IUriNode)t.Object, UriRefType.QName, tempNamespaceIDs, out rtype); if (rtype != UriRefType.QName) { //Generate a Temporary Namespace for the QName Type Reference this.GenerateTemporaryNamespace(context, (IUriNode)t.Object, ref nextNamespaceID, tempNamespaceIDs, doc); typeref = this.GenerateUriRef(context, (IUriNode)t.Object, UriRefType.QName, tempNamespaceIDs, out rtype); if (rtype == UriRefType.QName) { //Got a QName Type Reference in the Temporary Namespace OK typerefs.Add(t.Subject, typeref); if (context.Graph.Triples.WithSubject(t.Subject).Count() > 1) { context.TriplesDone.Add(t); } } } else { //Got a QName Type Reference OK //If no prefix drop the leading : if (typeref.StartsWith(":")) { typeref = typeref.Substring(1); } typerefs.Add(t.Subject, typeref); if (context.Graph.Triples.WithSubject(t.Subject).Count() > 1) { context.TriplesDone.Add(t); } } } } return(typerefs); }
private void GenerateCollectionOutput(RdfXmlWriterContext context, INode key) { OutputRdfCollection c = context.Collections[key]; c.HasBeenWritten = true; if (c.IsExplicit) { if (c.Triples.Count == 0) { // If No Triples then an isolated blank node so add rdf:nodeID and return context.Writer.WriteAttributeString("rdf", "nodeID", NamespaceMapper.RDF, context.BlankNodeMapper.GetOutputID(((IBlankNode)key).InternalID)); return; } // First see if there is a typed triple available (only applicable if we have more than one triple) INode rdfType = context.Graph.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfType)); Triple typeTriple = c.Triples.FirstOrDefault(t => t.Predicate.Equals(rdfType) && t.Object.NodeType == NodeType.Uri); if (typeTriple != null) { // Should be safe to invoke GenerateSubjectOutput but we can't allow rdf:Description GenerateSubjectOutput(context, c.Triples, false); } else { // Otherwise we invoke GeneratePredicateOutput (and use rdf:parseType="Resource" if there was more than 1 triple) context.Writer.WriteAttributeString("rdf", "parseType", NamespaceMapper.RDF, "Resource"); foreach (Triple t in c.Triples) { GeneratePredicateOutput(context, t); context.TriplesDone.Add(t); } } } else { // If No Triples then use rdf:about rdf:nil and return if (c.Triples.Count == 0) { context.Writer.WriteAttributeString("rdf", "about", NamespaceMapper.RDF, RdfSpecsHelper.RdfListNil); return; } // Going to need rdf:parseType="Resource" on current predicate context.Writer.WriteAttributeString("rdf", "parseType", NamespaceMapper.RDF, "Resource"); GenerateCollectionItemOutput(context, c); } }
private void GeneratePredicateNode(RdfXmlWriterContext context, INode p) { switch (p.NodeType) { case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Blank: throw new RdfOutputException(WriterErrorMessages.BlankPredicatesUnserializable("RDF/XML")); case NodeType.Literal: throw new RdfOutputException(WriterErrorMessages.LiteralPredicatesUnserializable("RDF/XML")); case NodeType.Uri: // OK UriRefType rtype; String predRef = this.GenerateUriRef(context, ((IUriNode)p).Uri, UriRefType.QName, out rtype); String prefix, uri; prefix = uri = null; if (rtype != UriRefType.QName) { this.GenerateTemporaryNamespace(context, (IUriNode)p, out prefix, out uri); predRef = this.GenerateUriRef(context, ((IUriNode)p).Uri, UriRefType.QName, out rtype); if (rtype != UriRefType.QName) { throw new RdfOutputException(WriterErrorMessages.UnreducablePropertyURIUnserializable + " - '" + p.ToString() + "'"); } } this.GenerateElement(context, predRef); // Add Temporary Namespace to current XML Element // CORE-431: This is unecessary and causes malformed XML under monotouch // if (prefix != null && uri != null) // { // context.Writer.WriteStartAttribute("xmlns", prefix, null); // context.Writer.WriteRaw(Uri.EscapeUriString(WriterHelper.EncodeForXml(uri))); // context.Writer.WriteEndAttribute(); // } break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } // Write the Predicate }
private XmlAttribute GenerateAttribute(RdfXmlWriterContext context, String qname, XmlDocument doc) { if (qname.Contains(':')) { if (qname.StartsWith(":")) { return(doc.CreateAttribute(qname.Substring(1))); } else { return(doc.CreateAttribute(qname, context.Graph.NamespaceMap.GetNamespaceUri(qname.Substring(0, qname.IndexOf(':'))).ToString())); } } else { return(doc.CreateAttribute(qname)); } }
private void GenerateElement(RdfXmlWriterContext context, String qname) { if (qname.Contains(':')) { if (qname.StartsWith(":")) { context.Writer.WriteStartElement(qname.Substring(1)); } else { String prefix = qname.Substring(0, qname.IndexOf(':')); String ns = (context.NamespaceMap.GetNestingLevel(prefix) > 1) ? context.NamespaceMap.GetNamespaceUri(prefix).AbsoluteUri : null; context.Writer.WriteStartElement(prefix, qname.Substring(prefix.Length + 1), ns); } } else { context.Writer.WriteStartElement(qname); } }
private void GenerateSimpleLiteralAttributes(RdfXmlWriterContext context, List <Triple> ts) { // If nothing to do then return if (ts.Count == 0) { return; } // Otherwise attach each Simple Literal directly to the Subject foreach (Triple t in ts) { UriRefType outType; IUriNode p = (IUriNode)t.Predicate; String uriref = GenerateUriRef(context, p.Uri, UriRefType.QName, out outType); if (outType != UriRefType.QName) { // Need to generate a temporary namespace String tempPrefix, tempUri; GenerateTemporaryNamespace(context, p, out tempPrefix, out tempUri); context.Writer.WriteAttributeString("xmlns", tempPrefix, null, Uri.EscapeUriString(tempUri)); uriref = GenerateUriRef(context, p.Uri, UriRefType.QName, out outType); if (outType != UriRefType.QName) { throw new RdfOutputException(WriterErrorMessages.UnreducablePropertyURIUnserializable); } } // Output Literal Attribute using the resulting QName if (uriref.Contains(':')) { // Create an attribute in appropriate namespace String ns = context.NamespaceMap.GetNamespaceUri(uriref.Substring(0, uriref.IndexOf(':'))).AbsoluteUri; context.Writer.WriteAttributeString(uriref.Substring(0, uriref.IndexOf(':')), uriref.Substring(uriref.IndexOf(':') + 1), ns, t.Object.ToString()); } else { // Create an attribute in the default namespace context.Writer.WriteAttributeString(uriref, t.Object.ToString()); } } }
private XmlElement GeneratePredicateNode(RdfXmlWriterContext context, INode p, ref int nextNamespaceID, List <String> tempNamespaces, XmlDocument doc, XmlElement subj) { XmlElement pred; switch (p.NodeType) { case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Blank: throw new RdfOutputException(WriterErrorMessages.BlankPredicatesUnserializable("RDF/XML")); case NodeType.Literal: throw new RdfOutputException(WriterErrorMessages.LiteralPredicatesUnserializable("RDF/XML")); case NodeType.Uri: //OK UriRefType rtype; String predRef = this.GenerateUriRef(context, (IUriNode)p, UriRefType.QName, tempNamespaces, out rtype); if (rtype != UriRefType.QName) { this.GenerateTemporaryNamespace(context, (IUriNode)p, ref nextNamespaceID, tempNamespaces, doc); predRef = this.GenerateUriRef(context, (IUriNode)p, UriRefType.QName, tempNamespaces, out rtype); if (rtype != UriRefType.QName) { throw new RdfOutputException(WriterErrorMessages.UnreducablePropertyURIUnserializable + " - '" + p.ToString() + "'"); } } pred = this.GenerateElement(context, predRef, doc); break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } //Write the Predicate subj.AppendChild(pred); return(pred); }
private void GenerateLiteralOutput(RdfXmlWriterContext context, ILiteralNode lit) { if (!lit.Language.Equals(String.Empty)) { context.Writer.WriteAttributeString("xml", "lang", null, lit.Language); context.Writer.WriteString(lit.Value); } else if (lit.DataType != null) { if (RdfSpecsHelper.RdfXmlLiteral.Equals(lit.DataType.AbsoluteUri)) { context.Writer.WriteAttributeString("rdf", "parseType", null, "Literal"); context.Writer.WriteRaw(lit.Value); } else { UriRefType refType; String dtUri = this.GenerateUriRef(context, lit.DataType, UriRefType.UriRef, out refType); if (refType == UriRefType.Uri) { context.Writer.WriteAttributeString("rdf", "datatype", null, lit.DataType.AbsoluteUri);//Uri.EscapeUriString(lit.DataType.ToString())); } else if (refType == UriRefType.UriRef) { context.Writer.WriteStartAttribute("rdf", "datatype", null); context.Writer.WriteRaw(dtUri); context.Writer.WriteEndAttribute(); } context.Writer.WriteString(lit.Value); } } else { // context.Writer.WriteRaw(WriterHelper.EncodeForXml(lit.Value)); context.Writer.WriteString(lit.Value); } }
/// <summary> /// Saves a Graph to an arbitrary output stream /// </summary> /// <param name="g">Graph to save</param> /// <param name="output">Stream to save to</param> public void Save(IGraph g, TextWriter output) { try { g.NamespaceMap.Import(this._defaultNamespaces); g.NamespaceMap.AddNamespace("rdf", new Uri(NamespaceMapper.RDF)); RdfXmlWriterContext context = new RdfXmlWriterContext(g, output); this.GenerateOutput(context); output.Close(); } catch { try { //Close the Output Stream output.Close(); } catch { //No Catch actions here } throw; } }
/// <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(this._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 = this._compressionLevel; context.UseDtd = this._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)) { 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);//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 = this.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)) { this.GenerateCollectionOutput(context, t.Subject); } else { context.Writer.WriteAttributeString("rdf", "nodeID", null, context.BlankNodeMapper.GetOutputID(((IBlankNode)t.Subject).InternalID)); } break; case NodeType.Uri: this.GenerateUriOutput(context, (IUriNode)t.Subject, "rdf:about"); break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } // Write the Predicate context.NamespaceMap.IncrementNesting(); this.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(); this.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(); this.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 this.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; this.GenerateLiteralOutput(context, lit); break; case NodeType.Uri: this.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); } this.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)); this.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(); }
private void GenerateObjectOutput(RdfXmlWriterContext context, Triple t) { // Take different actions depending on the Node Type to be written switch (t.Object.NodeType) { case NodeType.Blank: if (context.Collections.ContainsKey(t.Object)) { // Blank Node has a collection associated with it GenerateCollectionOutput(context, t.Object); } else { // Isolated Blank Node so use nodeID context.Writer.WriteAttributeString("rdf", "nodeID", NamespaceMapper.RDF, context.BlankNodeMapper.GetOutputID(((IBlankNode)t.Object).InternalID)); } break; case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: // Write as content of the current element ILiteralNode lit = (ILiteralNode)t.Object; if (lit.DataType != null) { if (lit.DataType.AbsoluteUri.Equals(RdfSpecsHelper.RdfXmlLiteral)) { // XML Literal context.Writer.WriteAttributeString("rdf", "parseType", NamespaceMapper.RDF, "Literal"); context.Writer.WriteRaw(lit.Value); } else { // Datatyped Literal context.Writer.WriteAttributeString("rdf", "datatype", NamespaceMapper.RDF, lit.DataType.AbsoluteUri); //Uri.EscapeUriString(lit.DataType.ToString())); context.Writer.WriteString(lit.Value); } } else if (!lit.Language.Equals(String.Empty)) { // Language specified Literal context.Writer.WriteAttributeString("xml", "lang", null, lit.Language); context.Writer.WriteString(lit.Value); } else { // Simple Literal context.Writer.WriteString(lit.Value); } break; case NodeType.Uri: // Simple rdf:resource // TODO: Compress this into UriRef where possible context.Writer.WriteAttributeString("rdf", "resource", NamespaceMapper.RDF, t.Object.ToString()); //Uri.EscapeUriString(t.Object.ToString())); break; case NodeType.Variable: throw new RdfOutputException(WriterErrorMessages.VariableNodesUnserializable("RDF/XML")); } }
private void GenerateSubjectOutput(RdfXmlWriterContext context, List <Triple> ts, bool allowRdfDescription) { // If nothing to do return if (ts.Count == 0) { return; } context.NamespaceMap.IncrementNesting(); // First off determine what the XML Element should be // If there is a rdf:type triple then create a typed node // Otherwise create a rdf:Description node INode rdfType = context.Graph.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfType)); Triple typeTriple = ts.FirstOrDefault(t => t.Predicate.Equals(rdfType) && t.Object.NodeType == NodeType.Uri); INode subj; if (typeTriple != null) { // Create Typed Node subj = typeTriple.Subject; // Generate the Type Reference creating a temporary namespace if necessary UriRefType outType; IUriNode typeNode = (IUriNode)typeTriple.Object; String uriref = GenerateUriRef(context, typeNode.Uri, UriRefType.QName, out outType); if (outType != UriRefType.QName) { // Need to generate a temporary namespace and try generating a QName again String tempPrefix, tempUri; GenerateTemporaryNamespace(context, typeNode, out tempPrefix, out tempUri); uriref = GenerateUriRef(context, typeNode.Uri, UriRefType.QName, out outType); if (outType != UriRefType.QName) { if (allowRdfDescription) { // Still couldn't generate a QName so fall back to rdf:Description // Note that in this case we don't remove the typeTriple from those to be written as we still need to // write it later context.Writer.WriteStartElement("rdf", "Description", NamespaceMapper.RDF); } else { throw new RdfOutputException(WriterErrorMessages.UnreducablePropertyURIUnserializable); } } else { if (uriref.Contains(':')) { // Type Node in relevant namespace context.Writer.WriteStartElement(uriref.Substring(0, uriref.IndexOf(':')), uriref.Substring(uriref.IndexOf(':') + 1), tempUri); } else { // Type Node in default namespace context.Writer.WriteStartElement(uriref); } ts.Remove(typeTriple); context.TriplesDone.Add(typeTriple); } // Remember to define the temporary namespace on the current element context.Writer.WriteAttributeString("xmlns", tempPrefix, null, Uri.EscapeUriString(tempUri)); } else { // Generated a valid QName if (uriref.Contains(':')) { // Create an element with appropriate namespace String ns = context.NamespaceMap.GetNamespaceUri(uriref.Substring(0, uriref.IndexOf(':'))).AbsoluteUri; context.Writer.WriteStartElement(uriref.Substring(0, uriref.IndexOf(':')), uriref.Substring(uriref.IndexOf(':') + 1), ns); } else { // Create an element in default namespace context.Writer.WriteStartElement(uriref); } context.TriplesDone.Add(typeTriple); ts.Remove(typeTriple); } } else { subj = ts.First().Subject; if (allowRdfDescription) { // Create rdf:Description Node context.Writer.WriteStartElement("rdf", "Description", NamespaceMapper.RDF); } else { throw new RdfOutputException(WriterErrorMessages.UnreducablePropertyURIUnserializable); } } // Always remember to add rdf:about or rdf:nodeID as appropriate if (subj.NodeType == NodeType.Uri) { context.Writer.WriteAttributeString("rdf", "about", NamespaceMapper.RDF, subj.ToString());//Uri.EscapeUriString(subj.ToString())); } else { // Can omit the rdf:nodeID if nesting level is > 2 i.e. not a top level subject node if (context.NamespaceMap.NestingLevel <= 2) { context.Writer.WriteAttributeString("rdf", "nodeID", NamespaceMapper.RDF, context.BlankNodeMapper.GetOutputID(((IBlankNode)subj).InternalID)); } } // If use of attributes is enabled we'll encode triples with simple literal objects // as attributes on the subject node directly if (context.UseAttributes) { // Next find any simple literals we can attach directly to the Subject Node List <Triple> simpleLiterals = new List <Triple>(); HashSet <INode> simpleLiteralPredicates = new HashSet <INode>(); foreach (Triple t in ts) { if (t.Object.NodeType == NodeType.Literal) { ILiteralNode lit = (ILiteralNode)t.Object; if (lit.DataType == null && lit.Language.Equals(String.Empty)) { if (!simpleLiteralPredicates.Contains(t.Predicate)) { simpleLiteralPredicates.Add(t.Predicate); simpleLiterals.Add(t); } } } } // Now go ahead and attach these to the Subject Node as attributes GenerateSimpleLiteralAttributes(context, simpleLiterals); simpleLiterals.ForEach(t => context.TriplesDone.Add(t)); simpleLiterals.ForEach(t => ts.Remove(t)); } // Then generate Predicate Output for each remaining Triple foreach (Triple t in ts) { GeneratePredicateOutput(context, t); context.TriplesDone.Add(t); } // Also check for the rare case where the subject is the key to a collection if (context.Collections.ContainsKey(subj)) { OutputRdfCollection collection = context.Collections[subj]; if (!collection.IsExplicit) { GenerateCollectionItemOutput(context, collection); collection.HasBeenWritten = true; } } context.Writer.WriteEndElement(); context.NamespaceMap.DecrementNesting(); }
/// <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(); }
/// <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); } }
private void GenerateCollectionOutput(RdfXmlWriterContext context, INode key, XmlElement pred, ref int nextNamespaceID, List <String> tempNamespaces, XmlDocument doc) { OutputRdfCollection c = context.Collections[key]; c.HasBeenWritten = true; if (!c.IsExplicit) { XmlAttribute parseType; if (pred.ParentNode != doc.DocumentElement) { //Need to set the Predicate to have a rdf:parseType of Resource parseType = doc.CreateAttribute("rdf:parseType", NamespaceMapper.RDF); parseType.Value = "Resource"; pred.Attributes.Append(parseType); } XmlElement first, rest; while (c.Triples.Count > 0) { //Get the Next Item and generate rdf:first and rdf:rest Nodes INode next = c.Triples.First().Object; c.Triples.RemoveAt(0); first = doc.CreateElement("rdf:first", NamespaceMapper.RDF); rest = doc.CreateElement("rdf:rest", NamespaceMapper.RDF); pred.AppendChild(first); pred.AppendChild(rest); //Set the value of the rdf:first Item switch (next.NodeType) { case NodeType.Blank: XmlAttribute nodeID = doc.CreateAttribute("rdf:nodeID", NamespaceMapper.RDF); nodeID.Value = ((IBlankNode)next).InternalID; first.Attributes.Append(nodeID); break; case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: this.GenerateLiteralOutput(context, (ILiteralNode)next, first, doc); break; case NodeType.Uri: this.GenerateUriOutput(context, (IUriNode)next, "rdf:resource", tempNamespaces, first, doc); break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } if (c.Triples.Count >= 1) { //Set Parse Type to resource parseType = doc.CreateAttribute("rdf:parseType", NamespaceMapper.RDF); parseType.Value = "Resource"; rest.Attributes.Append(parseType); pred = rest; } else { //Terminate list with an rdf:nil XmlAttribute res = doc.CreateAttribute("rdf:resource"); res.InnerXml = "&rdf;nil"; rest.Attributes.Append(res); } } } else { if (c.Triples.Count == 0) { //Terminate the Blank Node triple by adding a rdf:nodeID attribute XmlAttribute nodeID = doc.CreateAttribute("rdf:nodeID", NamespaceMapper.RDF); nodeID.Value = ((IBlankNode)key).InternalID; pred.Attributes.Append(nodeID); } else { //Need to set the Predicate to have a rdf:parseType of Resource if (pred.Name != "rdf:Description" && pred.ParentNode != doc.DocumentElement) { XmlAttribute parseType = doc.CreateAttribute("rdf:parseType", NamespaceMapper.RDF); parseType.Value = "Resource"; pred.Attributes.Append(parseType); } //Output the Predicate Object list while (c.Triples.Count > 0) { INode nextPred = c.Triples.First().Predicate; INode nextObj = c.Triples.First().Object; c.Triples.RemoveAt(0); XmlElement p; //Generate the predicate p = this.GeneratePredicateNode(context, nextPred, ref nextNamespaceID, tempNamespaces, doc, pred); //Output the Object switch (nextObj.NodeType) { case NodeType.Blank: if (context.Collections.ContainsKey(nextObj)) { //Output a Collection this.GenerateCollectionOutput(context, nextObj, p, ref nextNamespaceID, tempNamespaces, doc); } else { XmlAttribute nodeID = doc.CreateAttribute("rdf:nodeID", NamespaceMapper.RDF); nodeID.Value = ((IBlankNode)nextObj).InternalID; p.Attributes.Append(nodeID); } break; case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: this.GenerateLiteralOutput(context, (ILiteralNode)nextObj, p, doc); break; case NodeType.Uri: this.GenerateUriOutput(context, (IUriNode)nextObj, "rdf:resource", tempNamespaces, p, doc); break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } } } } }
private void GenerateCollectionOutput(RdfXmlWriterContext context, INode key) { OutputRdfCollection c = context.Collections[key]; if (!c.IsExplicit) { if (context.NamespaceMap.NestingLevel > 2) { // Need to set the Predicate to have a rdf:parseType of Resource context.Writer.WriteAttributeString("rdf", "parseType", NamespaceMapper.RDF, "Resource"); } int length = c.Triples.Count; while (c.Triples.Count > 0) { // Get the Next Item and generate the rdf:first element INode next = c.Triples.First().Object; c.Triples.RemoveAt(0); context.NamespaceMap.IncrementNesting(); context.Writer.WriteStartElement("rdf", "first", NamespaceMapper.RDF); // Set the value of the rdf:first Item switch (next.NodeType) { case NodeType.Blank: context.Writer.WriteAttributeString("rdf", "nodeID", NamespaceMapper.RDF, context.BlankNodeMapper.GetOutputID(((IBlankNode)next).InternalID)); break; case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: this.GenerateLiteralOutput(context, (ILiteralNode)next); break; case NodeType.Uri: this.GenerateUriOutput(context, (IUriNode)next, "rdf:resource"); break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } // Now generate the rdf:rest element context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndElement(); context.NamespaceMap.IncrementNesting(); context.Writer.WriteStartElement("rdf", "rest", NamespaceMapper.RDF); if (c.Triples.Count >= 1) { // Set Parse Type to resource context.Writer.WriteAttributeString("rdf", "parseType", NamespaceMapper.RDF, "Resource"); } else { // Terminate list with an rdf:nil context.Writer.WriteStartAttribute("rdf", "resource", NamespaceMapper.RDF); if (context.UseDtd) { context.Writer.WriteRaw("&rdf;nil"); } else { context.Writer.WriteRaw(NamespaceMapper.RDF + "nil"); } context.Writer.WriteEndAttribute(); } } for (int i = 0; i < length; i++) { context.NamespaceMap.DecrementNesting(); context.Writer.WriteEndElement(); } } else { if (c.Triples.Count == 0) { // Terminate the Blank Node triple by adding a rdf:nodeID attribute context.Writer.WriteAttributeString("rdf", "nodeID", NamespaceMapper.RDF, context.BlankNodeMapper.GetOutputID(((IBlankNode)key).InternalID)); } else { // Need to set the Predicate to have a rdf:parseType of Resource if (context.NamespaceMap.NestingLevel > 2) { // Need to set the Predicate to have a rdf:parseType of Resource context.Writer.WriteAttributeString("rdf", "parseType", NamespaceMapper.RDF, "Resource"); } // Output the Predicate Object list while (c.Triples.Count > 0) { Triple t = c.Triples[0]; c.Triples.RemoveAt(0); INode nextPred = t.Predicate; INode nextObj = t.Object; // Generate the predicate this.GeneratePredicateNode(context, nextPred); // Output the Object switch (nextObj.NodeType) { case NodeType.Blank: if (context.Collections.ContainsKey(nextObj)) { // Output a Collection this.GenerateCollectionOutput(context, nextObj); } else { context.Writer.WriteAttributeString("rdf", "nodeID", NamespaceMapper.RDF, context.BlankNodeMapper.GetOutputID(((IBlankNode)key).InternalID)); } break; case NodeType.GraphLiteral: throw new RdfOutputException(WriterErrorMessages.GraphLiteralsUnserializable("RDF/XML")); case NodeType.Literal: this.GenerateLiteralOutput(context, (ILiteralNode)nextObj); break; case NodeType.Uri: this.GenerateUriOutput(context, (IUriNode)nextObj, "rdf:resource"); break; default: throw new RdfOutputException(WriterErrorMessages.UnknownNodeTypeUnserializable("RDF/XML")); } context.Writer.WriteEndElement(); } } } }
private void GenerateCollectionOutput(RdfXmlWriterContext context, INode key) { OutputRdfCollection c = context.Collections[key]; c.HasBeenWritten = true; if (c.IsExplicit) { if (c.Triples.Count == 0) { //If No Triples then an isolated blank node so add rdf:nodeID and return context.Writer.WriteAttributeString("rdf", "nodeID", NamespaceMapper.RDF, context.BlankNodeMapper.GetOutputID(((IBlankNode)key).InternalID)); return; } //First see if there is a typed triple available INode rdfType = context.Graph.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfType)); Triple typeTriple = c.Triples.FirstOrDefault(t => t.Predicate.Equals(rdfType) && t.Object.NodeType == NodeType.Uri); if (typeTriple != null) { //Should be safe to invoke GenerateSubjectOutput but we can't allow rdf:Description this.GenerateSubjectOutput(context, c.Triples, false); } else { //Otherwise we use rdf:parseType="Resource" and invoke GeneratePredicateOutput context.Writer.WriteAttributeString("rdf", "parseType", NamespaceMapper.RDF, "Resource"); foreach (Triple t in c.Triples) { this.GeneratePredicateOutput(context, t); context.TriplesDone.Add(t); } } } else { //If No Triples then use rdf:about rdf:nil and return if (c.Triples.Count == 0) { context.Writer.WriteAttributeString("rdf", "about", NamespaceMapper.RDF, RdfSpecsHelper.RdfListNil); return; } //Going to need rdf:parseType="Resource" on current predicate context.Writer.WriteAttributeString("rdf", "parseType", NamespaceMapper.RDF, "Resource"); //Then output the elements of the Collection int toClose = c.Triples.Count; while (c.Triples.Count > 0) { Triple t = c.Triples[0]; c.Triples.RemoveAt(0); //rdf:first Node context.Writer.WriteStartElement("rdf", "first", NamespaceMapper.RDF); this.GenerateObjectOutput(context, t); context.TriplesDone.Add(t); context.Writer.WriteEndElement(); //rdf:rest Node context.Writer.WriteStartElement("rdf", "rest", NamespaceMapper.RDF); //context.Writer.WriteAttributeString("rdf", "parseType", NamespaceMapper.RDF, "Resource"); } //Terminate the list and close all the open rdf:rest elements context.Writer.WriteAttributeString("rdf", "resource", NamespaceMapper.RDF, RdfSpecsHelper.RdfListNil); for (int i = 0; i < toClose; i++) { context.Writer.WriteEndElement(); } } }