summaryrefslogtreecommitdiff
path: root/rdflib/plugins/serializers/trix.py
blob: fceec6bdd2e2ccdbed8721a42208c7d93106a84f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
from rdflib.serializer import Serializer
from rdflib.plugins.serializers.xmlwriter import XMLWriter

from rdflib.term import URIRef, Literal, BNode
from rdflib.namespace import Namespace

from rdflib.graph import Graph, ConjunctiveGraph

from six import text_type, b

__all__ = ['TriXSerializer']

# TODO: Move this somewhere central
TRIXNS = Namespace("http://www.w3.org/2004/03/trix/trix-1/")
XMLNS = Namespace("http://www.w3.org/XML/1998/namespace")


class TriXSerializer(Serializer):
    def __init__(self, store):
        super(TriXSerializer, self).__init__(store)
        if not store.context_aware:
            raise Exception(
                "TriX serialization only makes sense for context-aware stores")

    def serialize(self, stream, base=None, encoding=None, **args):

        nm = self.store.namespace_manager

        self.writer = XMLWriter(stream, nm, encoding, extra_ns={"": TRIXNS})

        self.writer.push(TRIXNS[u"TriX"])
        self.writer.namespaces()

        if isinstance(self.store, ConjunctiveGraph):
            for subgraph in self.store.contexts():
                self._writeGraph(subgraph)
        elif isinstance(self.store, Graph):
            self._writeGraph(self.store)
        else:
            raise Exception("Unknown graph type: " + type(self.store))

        self.writer.pop()
        stream.write(b("\n"))

    def _writeGraph(self, graph):
        self.writer.push(TRIXNS[u"graph"])
        if isinstance(graph.identifier, URIRef):
            self.writer.element(
                TRIXNS[u"uri"], content=text_type(graph.identifier))

        for triple in graph.triples((None, None, None)):
            self._writeTriple(triple)
        self.writer.pop()

    def _writeTriple(self, triple):
        self.writer.push(TRIXNS[u"triple"])
        for component in triple:
            if isinstance(component, URIRef):
                self.writer.element(TRIXNS[u"uri"],
                                    content=text_type(component))
            elif isinstance(component, BNode):
                self.writer.element(TRIXNS[u"id"],
                                    content=text_type(component))
            elif isinstance(component, Literal):
                if component.datatype:
                    self.writer.element(TRIXNS[u"typedLiteral"],
                                        content=text_type(component),
                                        attributes={TRIXNS[u"datatype"]:
                                                    text_type(component.datatype)})
                elif component.language:
                    self.writer.element(TRIXNS[u"plainLiteral"],
                                        content=text_type(component),
                                        attributes={XMLNS[u"lang"]:
                                                    text_type(component.language)})
                else:
                    self.writer.element(TRIXNS[u"plainLiteral"],
                                        content=text_type(component))
        self.writer.pop()