8 public class N3Writer
: RdfWriter
{
11 bool hasWritten
= false;
14 string lastSubject
= null, lastPredicate
= null;
18 Formats format
= Formats
.Turtle
;
26 public N3Writer(string file
) : this(file
, null) { }
28 public N3Writer(string file
, NamespaceManager ns
) : this(GetWriter(file
), ns
) { }
30 public N3Writer(TextWriter writer
) : this(writer
, null) { }
32 public N3Writer(TextWriter writer
, NamespaceManager ns
) {
33 this.writer
= writer
; this.ns
= ns
;
36 public override NamespaceManager Namespaces { get { return ns; }
}
38 public Formats Format { get { return format; }
set { format = value; }
}
40 public override void WriteStatement(string subj
, string pred
, string obj
) {
41 WriteStatement2(URI(subj
), URI(pred
), URI(obj
));
44 public override void WriteStatement(string subj
, string pred
, Literal literal
) {
45 WriteStatement2(URI(subj
), URI(pred
), literal
.ToString());
48 public override string CreateAnonymousEntity() {
49 return "_:anon" + (anonCounter
++);
52 public override void Close() {
56 writer
.WriteLine(".");
63 private string URI(string uri
) {
64 if (uri
.StartsWith("_:anon")) return uri
;
65 if (BaseUri
!= null && uri
.StartsWith(BaseUri
)) {
66 int len
= BaseUri
.Length
;
68 for (int i
= len
; i
< uri
.Length
; i
++) {
69 if (!char.IsLetterOrDigit(uri
[i
])) { ok = false; break; }
72 return ":" + uri
.Substring(len
);
74 if (Format
== Formats
.NTriples
|| ns
== null) return "<" + Escape(uri
) + ">";
76 string ret
= ns
.Normalize(uri
);
77 if (ret
[0] != '<') return ret
;
79 return "<" + Escape(uri
) + ">";
82 private static char HexDigit(char c
, int digit
) {
83 int n
= (((int)c
) >> (digit
* 4)) & 0xF;
85 return (char)('0' + n
);
87 return (char)('A' + (n
-10));
90 internal static string Escape(string str
) {
91 // Check if any escaping is necessary, following the NTriples spec.
93 for (int i
= 0; i
< str
.Length
; i
++) {
95 if (!((c
>= 0x20 && c
<= 0x21) || (c
>= 0x23 && c
<= 0x5B) || (c
>= 0x5D && c
<= 0x7E))) {
101 if (!needed
) return str
;
103 StringBuilder b
= new StringBuilder();
104 for (int i
= 0; i
< str
.Length
; i
++) {
106 if ((c
>= 0x20 && c
<= 0x21) || (c
>= 0x23 && c
<= 0x5B) || (c
>= 0x5D && c
<= 0x7E)) {
108 } else if (c
== 0x9) {
110 } else if (c
== 0xA) {
112 } else if (c
== 0xD) {
114 } else if (c
== 0x22) {
116 } else if (c
== 0x5C) {
118 } else if (c
<= 0x8 || c
== 0xB || c
== 0xC || (c
>= 0xE && c
<= 0x1F) || (c
>= 0x7F && c
<= 0xFFFF)) {
120 b
.Append(HexDigit(c
, 3));
121 b
.Append(HexDigit(c
, 2));
122 b
.Append(HexDigit(c
, 1));
123 b
.Append(HexDigit(c
, 0));
124 /*} else if (c >= 0x10000) {
126 b.Append(HexDigit(c, 7));
127 b.Append(HexDigit(c, 6));
128 b.Append(HexDigit(c, 5));
129 b.Append(HexDigit(c, 4));
130 b.Append(HexDigit(c, 3));
131 b.Append(HexDigit(c, 2));
132 b.Append(HexDigit(c, 1));
133 b.Append(HexDigit(c, 0));*/
139 private void WriteStatement2(string subj
, string pred
, string obj
) {
142 // Write the prefix directives at the beginning.
143 if (!hasWritten
&& ns
!= null && !(Format
== Formats
.NTriples
)) {
144 foreach (string prefix
in ns
.GetPrefixes()) {
145 writer
.Write("@prefix ");
146 writer
.Write(prefix
);
148 writer
.Write(ns
.GetNamespace(prefix
));
149 writer
.Write("> .\n");
154 if (lastSubject
!= null && lastSubject
== subj
&& !(Format
== Formats
.NTriples
)) {
155 // Repeated predicate too.
156 if (lastPredicate
!= null && lastPredicate
== pred
) {
157 writer
.Write(",\n\t\t");
160 // Just a repeated subject.
162 writer
.Write(";\n\t");
165 lastPredicate
= pred
;
168 // The subject became the object. Abbreviate with
169 // is...of notation (Notation3 format only).
170 } else if (lastSubject
!= null && lastSubject
== obj
&& (Format
== Formats
.Notation3
)) {
171 writer
.Write(";\n\tis ");
175 lastPredicate
= null;
177 // Start a new statement.
187 lastPredicate
= pred
;
193 private void WriteThing(string text
) {