gonum.org/v1/gonum@v0.14.0/graph/formats/gexf12/gexf.go (about) 1 // Copyright ©2018 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package gexf12 implements marshaling and unmarshaling of GEXF1.2 documents. 6 // 7 // For details of GEXF see https://gephi.org/gexf/format/. 8 package gexf12 // import "gonum.org/v1/gonum/graph/formats/gexf12" 9 10 import ( 11 "bytes" 12 "encoding/xml" 13 "time" 14 ) 15 16 // BUG(kortschak): The namespace for GEFX1.2 is 1.2draft, though it has 17 // already been deprecated. There is no specification for 1.3, although 18 // it is being used in the wild. 19 20 // Content holds a GEFX graph and metadata. 21 type Content struct { 22 XMLName xml.Name `xml:"http://www.gexf.net/1.2draft gexf"` 23 Meta *Meta `xml:"meta,omitempty"` 24 Graph Graph `xml:"graph"` 25 // Version must be "1.2". 26 Version string `xml:"version,attr"` 27 Variant string `xml:"variant,attr,omitempty"` 28 } 29 30 // Meta holds optional metadata associated with the graph. 31 type Meta struct { 32 Creator string `xml:"creator,omitempty"` 33 Keywords string `xml:"keywords,omitempty"` 34 Description string `xml:"description,omitempty"` 35 LastModified time.Time `xml:"lastmodifieddate,attr,omitempty"` 36 } 37 38 // MarshalXML implements the xml.Marshaler interface. 39 func (t *Meta) MarshalXML(e *xml.Encoder, start xml.StartElement) error { 40 type T Meta 41 var layout struct { 42 *T 43 LastModified *xsdDate `xml:"lastmodifieddate,attr,omitempty"` 44 } 45 layout.T = (*T)(t) 46 layout.LastModified = (*xsdDate)(&layout.T.LastModified) 47 return e.EncodeElement(layout, start) 48 } 49 50 // UnmarshalXML implements the xml.Unmarshaler interface. 51 func (t *Meta) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 52 type T Meta 53 var overlay struct { 54 *T 55 LastModified *xsdDate `xml:"lastmodifieddate,attr,omitempty"` 56 } 57 overlay.T = (*T)(t) 58 overlay.LastModified = (*xsdDate)(&overlay.T.LastModified) 59 return d.DecodeElement(&overlay, &start) 60 } 61 62 // Graph stores the graph nodes, edges, dynamics and visualization data. 63 type Graph struct { 64 Attributes []Attributes `xml:"attributes"` 65 Nodes Nodes `xml:"nodes"` 66 Edges Edges `xml:"edges"` 67 // TimeFormat may be one of "integer", "double", "date" or "dateTime". 68 TimeFormat string `xml:"timeformat,attr,omitempty"` 69 Start string `xml:"start,attr,omitempty"` 70 StartOpen string `xml:"startopen,attr,omitempty"` 71 End string `xml:"end,attr,omitempty"` 72 EndOpen string `xml:"endopen,attr,omitempty"` 73 // DefaultEdgeType may be one of "directed", "undirected" or "mutual". 74 DefaultEdgeType string `xml:"defaultedgetype,attr,omitempty"` 75 // IDType may be one of "integer" or "string". 76 IDType string `xml:"idtype,attr,omitempty"` 77 // Mode may be "static" or "dynamic". 78 Mode string `xml:"mode,attr,omitempty"` 79 } 80 81 // Attributes holds a collection of potentially dynamic attributes 82 // associated with a graph. 83 type Attributes struct { 84 Attributes []Attribute `xml:"attribute,omitempty"` 85 // Class be one of "node" or "edge". 86 Class string `xml:"class,attr"` 87 // Mode may be "static" or "dynamic". 88 Mode string `xml:"mode,attr,omitempty"` 89 Start string `xml:"start,attr,omitempty"` 90 StartOpen string `xml:"startopen,attr,omitempty"` 91 End string `xml:"end,attr,omitempty"` 92 EndOpen string `xml:"endopen,attr,omitempty"` 93 } 94 95 // Attribute holds a single graph attribute. 96 type Attribute struct { 97 ID string `xml:"id,attr"` 98 Title string `xml:"title,attr"` 99 // Type may be one of "integer", "long", "double", "float", 100 // "boolean", "liststring", "string", or "anyURI". 101 Type string `xml:"type,attr"` 102 Default string `xml:"default,omitempty"` 103 Options string `xml:"options,omitempty"` 104 } 105 106 // Nodes holds a collection of nodes constituting a graph or subgraph. 107 type Nodes struct { 108 Count int `xml:"count,attr,omitempty"` 109 Nodes []Node `xml:"node,omitempty"` 110 } 111 112 // Node is a single node and its associated attributes. 113 type Node struct { 114 ID string `xml:"id,attr,omitempty"` 115 Label string `xml:"label,attr,omitempty"` 116 AttValues *AttValues `xml:"attvalues"` 117 Spells *Spells `xml:"spells"` 118 Nodes *Nodes `xml:"nodes"` 119 Edges *Edges `xml:"edges"` 120 ParentID string `xml:"pid,attr,omitempty"` 121 Parents *Parents `xml:"parents"` 122 Color *Color `xml:"http://www.gexf.net/1.2draft/viz color"` 123 Position *Position `xml:"http://www.gexf.net/1.2draft/viz position"` 124 Size *Size `xml:"http://www.gexf.net/1.2draft/viz size"` 125 Shape *NodeShape `xml:"http://www.gexf.net/1.2draft/viz shape"` 126 Start string `xml:"start,attr,omitempty"` 127 StartOpen string `xml:"startopen,attr,omitempty"` 128 End string `xml:"end,attr,omitempty"` 129 EndOpen string `xml:"endopen,attr,omitempty"` 130 } 131 132 // NodeShape holds the visual representation of a node with associated 133 // dynamics. 134 type NodeShape struct { 135 Spells *Spells `xml:"spells,omitempty"` 136 // Value be one of "disc", "square", "triangle", 137 // "diamond" or "image". 138 Shape string `xml:"value,attr"` 139 URI string `xml:"uri,attr,omitempty"` 140 Start string `xml:"start,attr,omitempty"` 141 StartOpen string `xml:"startopen,attr,omitempty"` 142 End string `xml:"end,attr,omitempty"` 143 EndOpen string `xml:"endopen,attr,omitempty"` 144 } 145 146 // Color represents a node or edge color and its associated dynamics. 147 type Color struct { 148 Spells *Spells `xml:"spells,omitempty"` 149 R byte `xml:"r,attr"` 150 G byte `xml:"g,attr"` 151 B byte `xml:"b,attr"` 152 A float64 `xml:"a,attr,omitempty"` 153 Start string `xml:"start,attr,omitempty"` 154 StartOpen string `xml:"startopen,attr,omitempty"` 155 End string `xml:"end,attr,omitempty"` 156 EndOpen string `xml:"endopen,attr,omitempty"` 157 } 158 159 // Edges holds a collection of edges constituting a graph or subgraph. 160 type Edges struct { 161 Count int `xml:"count,attr,omitempty"` 162 Edges []Edge `xml:"edge,omitempty"` 163 } 164 165 // Edge is a single edge and its associated attributes. 166 type Edge struct { 167 ID string `xml:"id,attr,omitempty"` 168 AttValues *AttValues `xml:"attvalues"` 169 Spells *Spells `xml:"spells"` 170 Color *Color `xml:"http://www.gexf.net/1.2draft/viz color"` 171 Thickness *Thickness `xml:"http://www.gexf.net/1.2draft/viz thickness"` 172 Shape *Edgeshape `xml:"http://www.gexf.net/1.2draft/viz shape"` 173 Start string `xml:"start,attr,omitempty"` 174 StartOpen string `xml:"startopen,attr,omitempty"` 175 End string `xml:"end,attr,omitempty"` 176 EndOpen string `xml:"endopen,attr,omitempty"` 177 // Type may be one of directed, undirected, mutual 178 Type string `xml:"type,attr,omitempty"` 179 Label string `xml:"label,attr,omitempty"` 180 Source string `xml:"source,attr"` 181 Target string `xml:"target,attr"` 182 Weight float64 `xml:"weight,attr,omitempty"` 183 } 184 185 // AttValues holds a collection of attribute values. 186 type AttValues struct { 187 AttValues []AttValue `xml:"attvalue,omitempty"` 188 } 189 190 // AttValues holds a single attribute value and its associated dynamics. 191 type AttValue struct { 192 For string `xml:"for,attr"` 193 Value string `xml:"value,attr"` 194 Start string `xml:"start,attr,omitempty"` 195 StartOpen string `xml:"startopen,attr,omitempty"` 196 End string `xml:"end,attr,omitempty"` 197 EndOpen string `xml:"endopen,attr,omitempty"` 198 } 199 200 // EdgeShape holds the visual representation of an edge with associated 201 // dynamics. 202 type Edgeshape struct { 203 // Shape be one of solid, dotted, dashed, double 204 Shape string `xml:"value,attr"` 205 Spells *Spells `xml:"spells,omitempty"` 206 Start string `xml:"start,attr,omitempty"` 207 StartOpen string `xml:"startopen,attr,omitempty"` 208 End string `xml:"end,attr,omitempty"` 209 EndOpen string `xml:"endopen,attr,omitempty"` 210 } 211 212 // Parents holds parent relationships between nodes in a hierarchical 213 // graph. 214 type Parents struct { 215 Parents []Parent `xml:"parent,omitempty"` 216 } 217 218 // Parent is a single parent relationship. 219 type Parent struct { 220 For string `xml:"for,attr"` 221 } 222 223 // Position hold the spatial position of a node and its dynamics. 224 type Position struct { 225 X float64 `xml:"x,attr"` 226 Y float64 `xml:"y,attr"` 227 Z float64 `xml:"z,attr"` 228 Spells *Spells `xml:"spells,omitempty"` 229 Start string `xml:"start,attr,omitempty"` 230 StartOpen string `xml:"startopen,attr,omitempty"` 231 End string `xml:"end,attr,omitempty"` 232 EndOpen string `xml:"endopen,attr,omitempty"` 233 } 234 235 // Size hold the visual size of a node and its dynamics. 236 type Size struct { 237 Value float64 `xml:"value,attr"` 238 Spells *Spells `xml:"http://www.gexf.net/1.2draft/viz spells,omitempty"` 239 Start string `xml:"start,attr,omitempty"` 240 StartOpen string `xml:"startopen,attr,omitempty"` 241 End string `xml:"end,attr,omitempty"` 242 EndOpen string `xml:"endopen,attr,omitempty"` 243 } 244 245 // Thickness hold the visual thickness of an edge and its dynamics. 246 type Thickness struct { 247 Value float64 `xml:"value,attr"` 248 Spells *Spells `xml:"http://www.gexf.net/1.2draft/viz spells,omitempty"` 249 Start string `xml:"start,attr,omitempty"` 250 StartOpen string `xml:"startopen,attr,omitempty"` 251 End string `xml:"end,attr,omitempty"` 252 EndOpen string `xml:"endopen,attr,omitempty"` 253 } 254 255 // Spells holds a collection of time dynamics for a graph entity. 256 type Spells struct { 257 Spells []Spell `xml:"spell"` 258 } 259 260 // Spell is a time interval. 261 type Spell struct { 262 Start string `xml:"start,attr,omitempty"` 263 StartOpen string `xml:"startopen,attr,omitempty"` 264 End string `xml:"end,attr,omitempty"` 265 EndOpen string `xml:"endopen,attr,omitempty"` 266 } 267 268 type xsdDate time.Time 269 270 func (t *xsdDate) UnmarshalText(text []byte) error { 271 return _unmarshalTime(text, (*time.Time)(t), "2006-01-02") 272 } 273 274 func (t xsdDate) MarshalText() ([]byte, error) { 275 return []byte((time.Time)(t).Format("2006-01-02")), nil 276 } 277 278 func (t xsdDate) MarshalXML(e *xml.Encoder, start xml.StartElement) error { 279 if (time.Time)(t).IsZero() { 280 return nil 281 } 282 m, err := t.MarshalText() 283 if err != nil { 284 return err 285 } 286 return e.EncodeElement(m, start) 287 } 288 289 func (t xsdDate) MarshalXMLAttr(name xml.Name) (xml.Attr, error) { 290 if (time.Time)(t).IsZero() { 291 return xml.Attr{}, nil 292 } 293 m, err := t.MarshalText() 294 return xml.Attr{Name: name, Value: string(m)}, err 295 } 296 297 func _unmarshalTime(text []byte, t *time.Time, format string) (err error) { 298 s := string(bytes.TrimSpace(text)) 299 *t, err = time.Parse(format, s) 300 if _, ok := err.(*time.ParseError); ok { 301 *t, err = time.Parse(format+"Z07:00", s) 302 } 303 return err 304 }