Module: Insika::Knowledge::GraphmlExport
- Defined in:
- lib/insika/knowledge.rb
Overview
The follow-up export shape (ยง5): one combined graph instead of one
file per concept โ nodes are concepts (name/type/description/
confidence/provenance as node data), edges are [[links]] resolved
against the SAME export set (a link to a concept outside the scope is
dropped, never a dangling edge). Directly consumable by Gephi/yEd/
graphify. No new dependency: hand-built and hand-escaped XML, the same
zero-dependency discipline the rest of this feature keeps.
Class Method Summary collapse
-
.build(concepts) ⇒ Object
concepts: [Concept.parse output, ...].
- .edges_for(concept, known_names) ⇒ Object
-
.escape(text) ⇒ Object
The five XML predefined entities โ no library needed for this subset.
- .node(concept) ⇒ Object
Class Method Details
.build(concepts) ⇒ Object
concepts: [Concept.parse output, ...]. -> String (one .graphml document).
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 |
# File 'lib/insika/knowledge.rb', line 633 def build(concepts) names = concepts.map { |c| c[:name] } nodes = concepts.map { |c| node(c) }.join("\n") edges = concepts.flat_map { |c| edges_for(c, names) }.join("\n") <<~XML <?xml version="1.0" encoding="UTF-8"?> <graphml xmlns="http://graphml.graphdrawing.org/xmlns"> <key id="name" for="node" attr.name="name" attr.type="string"/> <key id="type" for="node" attr.name="type" attr.type="string"/> <key id="description" for="node" attr.name="description" attr.type="string"/> <key id="confidence" for="node" attr.name="confidence" attr.type="double"/> <key id="provenance" for="node" attr.name="provenance" attr.type="string"/> <graph id="knowledge" edgedefault="directed"> #{nodes} #{edges} </graph> </graphml> XML end |
.edges_for(concept, known_names) ⇒ Object
665 666 667 668 669 |
# File 'lib/insika/knowledge.rb', line 665 def edges_for(concept, known_names) Concept.links(concept[:body]).select { |name| known_names.include?(name) }.map do |target| %( <edge source="#{escape(concept[:name])}" target="#{escape(target)}"/>) end end |
.escape(text) ⇒ Object
The five XML predefined entities โ no library needed for this subset.
Order matters: & first, or every other substitution's own & gets
re-escaped.
674 675 676 677 |
# File 'lib/insika/knowledge.rb', line 674 def escape(text) text.to_s.gsub("&", "&").gsub("<", "<").gsub(">", ">") .gsub('"', """).gsub("'", "'") end |
.node(concept) ⇒ Object
653 654 655 656 657 658 659 660 661 662 663 |
# File 'lib/insika/knowledge.rb', line 653 def node(concept) <<~NODE.chomp <node id="#{escape(concept[:name])}"> <data key="name">#{escape(concept[:name])}</data> <data key="type">#{escape(concept[:type])}</data> <data key="description">#{escape(concept[:description])}</data> <data key="confidence">#{concept[:confidence]}</data> <data key="provenance">#{escape(concept[:provenance])}</data> </node> NODE end |