Class: RdfContext::XmlSerializer
- Inherits:
-
RecursiveSerializer
- Object
- AbstractSerializer
- RecursiveSerializer
- RdfContext::XmlSerializer
- Defined in:
- lib/rdf_context/serializer/xml_serializer.rb
Overview
Serialize RDF graphs in NTriples format
Constant Summary collapse
- VALID_ATTRIBUTES =
[:none, :untyped, :typed]
Constants inherited from RecursiveSerializer
RecursiveSerializer::INDENT_STRING, RecursiveSerializer::MAX_DEPTH
Instance Attribute Summary
Attributes inherited from AbstractSerializer
Instance Method Summary collapse
-
#initialize(graph) ⇒ XmlSerializer
constructor
New XmlSerializer.
-
#predicate(prop, object, node, is_unique) ⇒ Object
protected
Output a predicate into the specified node.
- #preprocess_triple(triple) ⇒ Object protected
-
#serialize(stream, options = {})
Serialize the graph.
- #subject(subject, parent_node) ⇒ Object protected
Methods inherited from RecursiveSerializer
#add_namespace, #get_qname, #indent, #is_done?, #order_subjects, #predicate_order, #preprocess, #ref_count, #reset, #sort_properties, #subject_done, #top_classes, #uri_binding, #write
Methods inherited from AbstractSerializer
Constructor Details
#initialize(graph) ⇒ XmlSerializer
New XmlSerializer
9 10 11 12 |
# File 'lib/rdf_context/serializer/xml_serializer.rb', line 9 def initialize(graph) super @force_RDF_about = {} end |
Instance Method Details
#predicate(prop, object, node, is_unique) ⇒ Object (protected)
Output a predicate into the specified node.
If is_unique is true, this predicate may be able to be serialized as an attribute
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/rdf_context/serializer/xml_serializer.rb', line 145 def predicate(prop, object, node, is_unique) qname = prop.to_qname(uri_binding) raise RdfException, "No qname generated for <#{prop}>" unless qname # See if we can serialize as attribute. # * untyped attributes that aren't duplicated where xml:lang == @lang # * typed attributes that aren't duplicated if @dt_as_attr is true # * rdf:type as_attr = false as_attr ||= true if [:untyped, :typed].include?(@attributes) && prop == RDF_TYPE # Untyped attribute with no lang, or whos lang is the same as the default and RDF_TYPE as_attr ||= true if [:untyped, :typed].include?(@attributes) && (object.is_a?(Literal) && object.untyped? && (object.lang.nil? || object.lang == @lang)) as_attr ||= true if [:typed].include?(@attributes) && object.is_a?(Literal) && object.typed? as_attr = false unless is_unique # Can't do as an attr if the qname has no prefix and there is no prefixed version if @default_ns && prop.namespace.uri == @default_ns.uri if as_attr if @prefixed_default_ns qname = "#{@prefixed_default_ns.prefix}:#{prop.short_name}" else as_attr = false end else qname = prop.short_name end end puts "predicate: #{qname}, as_attr: #{as_attr}, object: #{object.inspect}, done: #{is_done?(object)}, sub: #{@subjects.include?(object)}" if ::RdfContext::debug? qname = "rdf:li" if qname.match(/rdf:_\d+/) pred_node = Nokogiri::XML::Element.new(qname, node.document) if object.is_a?(Literal) || is_done?(object) || !@subjects.include?(object) # Literals or references to objects that aren't subjects, or that have already been serialized args = object.xml_args puts "predicate: args=#{args.inspect}" if ::RdfContext::debug? attrs = args.pop if as_attr # Serialize as attribute pred_node.unlink pred_node = nil node[qname] = object.is_a?(URIRef) ? relativize(object) : object.to_s else # Serialize as element attrs.each_pair do |a, av| next if a == "xml:lang" && av == @lang # Lang already specified, don't repeat av = relativize(object) if a == "#{RDF_NS.prefix}:resource" puts " elt attr #{a}=#{av}" if ::RdfContext::debug? pred_node[a] = av.to_s end puts " elt #{'xmllit ' if object.is_a?(Literal) && object.xmlliteral?}content=#{args.first}" if ::RdfContext::debug? && !args.empty? if object.is_a?(Literal) && object.xmlliteral? pred_node.add_child(Nokogiri::XML::CharacterData.new(args.first, node.document)) elsif args.first pred_node.content = args.first unless args.empty? end end else # Check to see if it can be serialized as a collection col = @graph.seq(object) conformant_list = col.all? {|item| !item.is_a?(Literal)} o_props = @graph.properties(object) if conformant_list && o_props[RDF_NS.first.to_s] # Serialize list as parseType="Collection" pred_node["rdf:parseType"] = "Collection" col.each do |item| # Mark the BNode subject of each item as being complete, so that it is not serialized @graph.triples(Triple.new(nil, RDF_NS.first, item)) do |triple, ctx| subject_done(triple.subject) end @force_RDF_about[item] = true subject(item, pred_node) end else if @depth < @max_depth @depth += 1 subject(object, pred_node) @depth -= 1 elsif object.is_a?(BNode) pred_node["rdf:nodeID"] = object.identifier else pred_node["rdf:resource"] = relativize(object) end end end node.add_child(pred_node) if pred_node end |
#preprocess_triple(triple) ⇒ Object (protected)
239 240 241 242 243 244 245 246 247 |
# File 'lib/rdf_context/serializer/xml_serializer.rb', line 239 def preprocess_triple(triple) super # Pre-fetch qnames, to fill namespaces get_qname(triple.predicate) get_qname(triple.object) if triple.predicate == RDF_TYPE @references[triple.predicate] = ref_count(triple.predicate) + 1 end |
#serialize(stream, options = {})
This method returns an undefined value.
Serialize the graph
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/rdf_context/serializer/xml_serializer.rb', line 26 def serialize(stream, = {}) @max_depth = [:max_depth] || 3 @base = [:base] @lang = [:lang] @attributes = [:attributes] || :none raise "Invalid attribute option '#{@attributes}', should be one of #{VALID_ATTRIBUTES.to_sentence}" unless VALID_ATTRIBUTES.include?(@attributes.to_sym) doc = Nokogiri::XML::Document.new puts "\nserialize: graph namespaces: #{@graph.nsbinding.inspect}" if ::RdfContext::debug? preprocess predicates = @graph.predicates.uniq namespaces = {} required_namespaces = {} predicates.each do |res| next unless res.is_a?(URIRef) if res.namespace add_namespace(res.namespace) else required_namespaces[res.base] = true end #puts "possible namespace for #{res}: #{res.namespace || %(<#{res.base}>)}" end add_namespace(RDF_NS) add_namespace(XML_NS) if @base || @lang # See if there's a default namespace, and favor it when generating element names. # Lookup an equivalent prefixed namespace for use in generating attributes @default_ns = @graph.namespace("") if @default_ns add_namespace(@default_ns) prefix = @graph.prefix(@default_ns.uri) @prefixed_default_ns = @graph.namespace(prefix) add_namespace(@prefixed_default_ns) if @prefixed_default_ns end # Add bindings for predicates not already having bindings tmp_ns = "ns0" required_namespaces.keys.each do |uri| puts "create namespace definition for #{uri}" if ::RdfContext::debug? add_namespace(Namespace.new(uri, tmp_ns)) tmp_ns = tmp_ns.succ end doc.root = Nokogiri::XML::Element.new("rdf:RDF", doc) @namespaces.each_pair do |p, ns| if p.to_s.empty? doc.root.default_namespace = ns.uri.to_s else doc.root.add_namespace(p, ns.uri.to_s) end end doc.root["xml:lang"] = @lang if @lang doc.root["xml:base"] = @base if @base # Add statements for each subject order_subjects.each do |subject| #puts "subj: #{subject.inspect}" subject(subject, doc.root) end doc.write_xml_to(stream, :encoding => "UTF-8", :indent => 2) end |
#subject(subject, parent_node) ⇒ Object (protected)
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/rdf_context/serializer/xml_serializer.rb', line 93 def subject(subject, parent_node) node = nil if !is_done?(subject) subject_done(subject) properties = @graph.properties(subject) prop_list = sort_properties(properties) puts "subject: #{subject.to_n3}, props: #{properties.inspect}" if ::RdfContext::debug? rdf_type, *rest = properties.fetch(RDF_TYPE.to_s, []) if rdf_type.is_a?(URIRef) element = get_qname(rdf_type) properties[RDF_TYPE.to_s] = rest type_ns = rdf_type.namespace rescue nil if type_ns && @default_ns && type_ns.uri == @default_ns.uri properties[RDF_TYPE.to_s] = rest element = rdf_type.short_name end end element ||= "rdf:Description" node = Nokogiri::XML::Element.new(element, parent_node.document) if subject.is_a?(BNode) # Only need nodeID if it's referenced elsewhere node["rdf:nodeID"] = subject.to_s if ref_count(subject) > (@depth == 0 ? 0 : 1) else node["rdf:about"] = relativize(subject) end prop_list.each do |prop| prop_ref = URIRef.new(prop) properties[prop].each do |object| @depth += 1 predicate(prop_ref, object, node, properties[prop].length == 1) @depth -= 1 end end elsif @force_RDF_about.include?(subject) puts "subject: #{subject.to_n3}, force about" if ::RdfContext::debug? node = Nokogiri::XML::Element.new("rdf:Description", parent_node.document) node["rdf:about"] = relativize(subject) @force_RDF_about.delete(subject) end parent_node.add_child(node) if node end |