Logo Search packages:      
Sourcecode: f-spot version File versions  Download package

XmlWriter.cs

using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Xml;

using SemWeb;

namespace SemWeb {
      public class RdfXmlWriter : RdfWriter {
            XmlWriter writer;
            NamespaceManager ns;
            
            XmlDocument doc;
            
            Hashtable nodeMap = new Hashtable();
            
            long anonCounter = 0;
            Hashtable anonAlloc = new Hashtable();
            
            public RdfXmlWriter(string file) : this(file, null) { }
            
            public RdfXmlWriter(string file, NamespaceManager ns) : this(GetWriter(file), ns) { }

            public RdfXmlWriter(TextWriter writer) : this(writer, null) { }
            
            public RdfXmlWriter(TextWriter writer, NamespaceManager ns) : this(NewWriter(writer), ns) { }
            
            private static XmlWriter NewWriter(TextWriter writer) {
                  XmlTextWriter ret = new XmlTextWriter(writer);
                  ret.Formatting = Formatting.Indented;
                  ret.Indentation = 1;
                  ret.IndentChar = '\t';
                  ret.Namespaces = true;
                  return ret;
            }
            
            public RdfXmlWriter(XmlWriter writer) : this(writer, null) { }
            
            public RdfXmlWriter(XmlWriter writer, NamespaceManager ns) {
                  if (ns == null)
                        ns = new NamespaceManager();
                  this.writer = writer;
                  this.ns = ns;
            }
            
            private void Start() {
                  if (doc != null) return;
                  doc = new XmlDocument();
                  
                  string rdfprefix = ns.GetPrefix(NS.RDF);
                  if (rdfprefix == null) {
                        if (ns.GetNamespace("rdf") == null) {
                              rdfprefix = "rdf";
                              ns.AddNamespace(NS.RDF, "rdf");
                        }
                  }
                  
                  XmlElement root = doc.CreateElement(rdfprefix + ":RDF", NS.RDF);
                  foreach (string prefix in ns.GetPrefixes())
                        root.SetAttribute("xmlns:" + prefix, ns.GetNamespace(prefix));
                  doc.AppendChild(root);
            }
            
            public override NamespaceManager Namespaces { get { return ns; } }
            
            char[] normalizechars = { '#', '/' };
            
            private void Normalize(string uri, out string prefix, out string localname) {
                  if (uri == "")
                        throw new InvalidOperationException("The empty URI cannot be used as an element node.");  
            
                  if (ns.Normalize(uri, out prefix, out localname))
                        return;
                        
                  // No namespace prefix was registered, so come up with something.
                  
                  int last = uri.LastIndexOfAny(normalizechars);
                  if (last <= 0)
                        throw new InvalidOperationException("No namespace was registered and no prefix could be automatically generated for <" + uri + ">");
                        
                  int prev = uri.LastIndexOfAny(normalizechars, last-1);
                  if (prev <= 0)
                        throw new InvalidOperationException("No namespace was registered and no prefix could be automatically generated for <" + uri + ">");
                  
                  string n = uri.Substring(0, last+1);
                  localname = uri.Substring(last+1);
                  
                  // TODO: Make sure the local name (here and anywhere in this
                  // class) is a valid XML name.
                  
                  if (Namespaces.GetPrefix(n) != null) {
                        prefix = Namespaces.GetPrefix(n);
                        return;
                  }
                  
                  prefix = uri.Substring(prev+1, last-prev-1);
                  
                  // Remove all non-xmlable (letter) characters.
                  StringBuilder newprefix = new StringBuilder();
                  foreach (char c in prefix)
                        if (char.IsLetter(c))
                              newprefix.Append(c);
                  prefix = newprefix.ToString();
                  
                  if (prefix.Length == 0) {
                        // There were no letters in the prefix!
                        prefix = "ns";
                  }
                  
                  if (Namespaces.GetNamespace(prefix) == null) {
                        doc.DocumentElement.SetAttribute("xmlns:" + prefix, n);
                        Namespaces.AddNamespace(n, prefix);
                        return;
                  }
                  
                  int ctr = 1;
                  while (true) {
                        if (Namespaces.GetNamespace(prefix + ctr) == null) {
                              prefix += ctr;
                              doc.DocumentElement.SetAttribute("xmlns:" + prefix, n);
                              Namespaces.AddNamespace(n, prefix);
                              return;
                        }
                        ctr++;
                  }
            }
            
            private void SetAttribute(XmlElement element, string nsuri, string prefix, string localname, string val) {
                  XmlAttribute attr = doc.CreateAttribute(prefix, localname, nsuri);
                  attr.InnerXml = val;
                  element.SetAttributeNode(attr);
            }
            
            private XmlElement GetNode(string uri, string type, XmlElement context) {
                  if (nodeMap.ContainsKey(uri))
                        return (XmlElement)nodeMap[uri];
                  
                  Start();                
                  
                  XmlElement node;
                  if (type == null) {
                        node = doc.CreateElement(ns.GetPrefix(NS.RDF) + ":Description", NS.RDF);
                  } else {
                        string prefix, localname;
                        Normalize(type, out prefix, out localname);
                        node = doc.CreateElement(prefix + ":" + localname, ns.GetNamespace(prefix));
                  }
                  
                  if (!anonAlloc.ContainsKey(uri)) {
                        SetAttribute(node, NS.RDF, ns.GetPrefix(NS.RDF), "about", uri);
                  } else {
                        SetAttribute(node, NS.RDF, ns.GetPrefix(NS.RDF), "nodeID", uri);
                  }
                  
                  if (context == null)
                        doc.DocumentElement.AppendChild(node);
                  else
                        context.AppendChild(node);
                  
                  nodeMap[uri] = node;
                  return node;
            }
            
            private XmlElement CreatePredicate(XmlElement subject, string predicate) {
                  string prefix, localname;
                  Normalize(predicate, out prefix, out localname);
                  XmlElement pred = doc.CreateElement(prefix + ":" + localname, ns.GetNamespace(prefix));
                  subject.AppendChild(pred);
                  return pred;
            }
            
            public override void WriteStatement(string subj, string pred, string obj) {
                  XmlElement subjnode = GetNode(subj, pred == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" ? obj : null, null);
                  if (pred == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") return;
                  
                  XmlElement prednode = CreatePredicate(subjnode, pred);
                  if (nodeMap.ContainsKey(obj)) {
                        if (!anonAlloc.ContainsKey(obj)) {
                              SetAttribute(prednode, NS.RDF, ns.GetPrefix(NS.RDF), "resource", obj);
                        } else {
                              SetAttribute(prednode, NS.RDF, ns.GetPrefix(NS.RDF), "nodeID", obj);
                        }
                  } else {
                        GetNode(obj, null, prednode);
                  }
            }
            
            public override void WriteStatement(string subj, string pred, Literal literal) {
                  XmlElement subjnode = GetNode(subj, null, null);
                  XmlElement prednode = CreatePredicate(subjnode, pred);
                  prednode.InnerText = literal.Value;
            }
            
            public override string CreateAnonymousEntity() {
                  string id = "anon" + (anonCounter++);
                  anonAlloc[id] = anonAlloc;
                  return id;
            }
            
            public override void Close() {
                  base.Close();
                  if (doc != null)
                        doc.WriteTo(writer);
                  //writer.Close();
            }
      }

      internal class RdfXmlWriter2 : RdfWriter {
            XmlWriter writer;
            NamespaceManager ns;
            NamespaceManager autons;
            
            long anonCounter = 0;
            string currentSubject = null;
            
            string rdf;
            
            public RdfXmlWriter2(string file) : this(file, null) { }
            
            public RdfXmlWriter2(string file, NamespaceManager ns) : this(GetWriter(file), ns) { }

            public RdfXmlWriter2(TextWriter writer) : this(writer, null) { }
            
            public RdfXmlWriter2(TextWriter writer, NamespaceManager ns) : this(NewWriter(writer), ns) { }
            
            private static XmlWriter NewWriter(TextWriter writer) {
                  XmlTextWriter ret = new XmlTextWriter(writer);
                  ret.Formatting = Formatting.Indented;
                  ret.Indentation = 1;
                  ret.IndentChar = '\t';
                  return ret;
            }
            
            public RdfXmlWriter2(XmlWriter writer) : this(writer, null) { }
            
            public RdfXmlWriter2(XmlWriter writer, NamespaceManager ns) {
                  if (ns == null)
                        ns = new NamespaceManager();
                  this.writer = writer;
                  this.ns = ns;
                  //autons = new AutoPrefixNamespaceManager(this.ns);
            }
            
            public override NamespaceManager Namespaces { get { return ns; } }
            
            private bool Open(string resource, string type) {
                  bool emittedType = false;
                  
                  if (currentSubject == null) {
                        rdf = autons.GetPrefix("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
                        writer.WriteStartElement(rdf + ":RDF");
                        foreach (string prefix in autons.GetPrefixes())
                              writer.WriteAttributeString("xmlns:" + prefix, autons.GetNamespace(prefix));
                  }
                  if (currentSubject != null && currentSubject != resource)
                        writer.WriteEndElement();
                  if (currentSubject == null || currentSubject != resource) {
                        currentSubject = resource;
                        
                        if (type == null)
                              writer.WriteStartElement(rdf + ":Description");
                        else {
                              writer.WriteStartElement(URI(type));
                              emittedType = true;
                        }
                        
                        writer.WriteAttributeString(rdf + ":about", resource);
                  }
                  
                  return emittedType;
            }
            
            public override void WriteStatement(string subj, string pred, string obj) {
                  if (Open(subj, pred == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" ? obj : null))
                        return;
                  writer.WriteStartElement(URI(pred));
                  writer.WriteAttributeString("rdf:resource", obj);
                  writer.WriteEndElement();
            }
            
            public override void WriteStatement(string subj, string pred, Literal literal) {
                  Open(subj, null);
                  writer.WriteStartElement(URI(pred));
                  // Should write language and datatype
                  writer.WriteString(literal.Value);
                  writer.WriteEndElement();
            }
            
            public override string CreateAnonymousEntity() {
                  return "_:anon" + (anonCounter++);
            }
            
            public override void Close() {
                  base.Close();
                  if (currentSubject != null) {
                        writer.WriteEndElement();
                        writer.WriteEndElement();
                  }
                  //writer.Close();
            }

            
            private string URI(string uri) {
                  if (uri.StartsWith("_:anon")) return uri;
                  string ret = autons.Normalize(uri);
                  if (ret.StartsWith("<"))
                        throw new InvalidOperationException("A namespace prefix must be defined for the URI " + ret + ".");
                  return ret;
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index