Skip to content

Commit d7d3ff0

Browse files
namedgraphclaude
andcommitted
Initialize 3D graph on document GraphMode; fix blank node merging
- layout.xsl: server-side GraphMode outputs a .graph-3d-canvas placeholder div instead of the 2D SVG renderer; client initializes ForceGraph3D - client.xsl: detect .graph-3d-canvas divs in ldh:rdf-document-response and call ldh:InitDocumentGraph3D (mirrors map/chart init pattern) - graph3d.xsl: add ldh:InitDocumentGraph3D named template for document mode - normalize-rdfxml.xsl: add 4th pass to prefix blank node IDs with a document-unique token, preventing ID collisions when merging multiple fetched RDF documents - merge-rdfxml.xsl: include blank node descriptions from new documents in the merge; split rdf:Description match to [@Rdf:about] for property merging and [@Rdf:nodeID] for copy-as-is Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9e916a2 commit d7d3ff0

File tree

5 files changed

+96
-9
lines changed

5 files changed

+96
-9
lines changed

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/graph3d.xsl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,51 @@ exclude-result-prefixes="#all"
255255
<span><xsl:value-of select="$node-label"/></span>
256256
</xsl:template>
257257

258+
<!-- DOCUMENT-MODE GRAPH INIT (called from ldh:rdf-document-response) -->
259+
260+
<xsl:template name="ldh:InitDocumentGraph3D">
261+
<xsl:param name="canvas" as="element()"/>
262+
<xsl:param name="canvas-id" as="xs:string"/>
263+
<xsl:param name="rdf-doc" as="document-node()"/>
264+
265+
<xsl:variable name="graphs" select="ixsl:get(ixsl:window(), 'LinkedDataHub.graphs')"/>
266+
<xsl:variable name="graph-state" as="item()">
267+
<xsl:call-template name="ldh:ForceGraph3D-init">
268+
<xsl:with-param name="graph-id" select="$canvas-id"/>
269+
<xsl:with-param name="container" select="$canvas"/>
270+
<xsl:with-param name="builder" select="ixsl:apply(ixsl:get(ixsl:window(), 'ForceGraph3D'), [])"/>
271+
<xsl:with-param name="graph-width" select="xs:double(ixsl:get($canvas, 'offsetWidth'))"/>
272+
<xsl:with-param name="graph-height" select="xs:double(600)"/>
273+
<xsl:with-param name="node-rel-size" select="xs:double(4)"/>
274+
<xsl:with-param name="link-width" select="xs:double(1.5)"/>
275+
<xsl:with-param name="node-label-color" select="'white'"/>
276+
<xsl:with-param name="node-label-text-height" select="xs:double(5)"/>
277+
<xsl:with-param name="node-label-position-y" select="xs:double(10)"/>
278+
<xsl:with-param name="link-label-color" select="'lightgrey'"/>
279+
<xsl:with-param name="link-label-text-height" select="xs:double(4)"/>
280+
<xsl:with-param name="link-force-distance" select="xs:double(100)"/>
281+
<xsl:with-param name="charge-force-strength" select="xs:double(-200)"/>
282+
<xsl:with-param name="node-click-event-name" select="'ForceGraph3DNodeClick'"/>
283+
<xsl:with-param name="node-dblclick-event-name" select="'ForceGraph3DNodeDblClick'"/>
284+
<xsl:with-param name="node-rightclick-event-name" select="'ForceGraph3DNodeRightClick'"/>
285+
<xsl:with-param name="node-hover-on-event-name" select="'ForceGraph3DNodeHoverOn'"/>
286+
<xsl:with-param name="node-hover-off-event-name" select="'ForceGraph3DNodeHoverOff'"/>
287+
<xsl:with-param name="link-click-event-name" select="'ForceGraph3DLinkClick'"/>
288+
<xsl:with-param name="background-click-event-name" select="'ForceGraph3DBackgroundClick'"/>
289+
</xsl:call-template>
290+
</xsl:variable>
291+
<ixsl:set-property name="document" select="$rdf-doc" object="$graph-state"/>
292+
<ixsl:set-property name="loaded-uris" select="ixsl:new('Array', [])" object="$graph-state"/>
293+
<ixsl:set-property name="{$canvas-id}" select="$graph-state" object="$graphs"/>
294+
295+
<xsl:variable name="graph-instance" select="ixsl:get($graph-state, 'instance')"/>
296+
<xsl:variable name="graph-data" as="item()">
297+
<xsl:apply-templates select="$rdf-doc" mode="ldh:ForceGraph3D-convert-data">
298+
<xsl:with-param name="show-stubs" select="true()" tunnel="yes"/>
299+
<xsl:with-param name="show-literals" select="false()" tunnel="yes"/>
300+
</xsl:apply-templates>
301+
</xsl:variable>
302+
<xsl:sequence select="ixsl:call($graph-instance, 'graphData', [$graph-data], map{'convert-args': false()})[current-date() lt xs:date('2000-01-01')]"/>
303+
</xsl:template>
304+
258305
</xsl:stylesheet>

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/merge-rdfxml.xsl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,19 @@
2222
<xsl:apply-templates select="@* | node()" mode="#current"/>
2323

2424
<xsl:variable name="existing-rdf" select="root(.)" as="document-node()"/>
25-
<!-- Add new descriptions that don't exist in the existing document -->
26-
<xsl:for-each select="$new-rdf/rdf:RDF/*[@rdf:about]">
27-
<xsl:if test="not(key('resources', @rdf:about, $existing-rdf))">
25+
<!-- Add new descriptions (URI-identified or blank nodes) that don't exist in the existing document -->
26+
<!-- Blank node IDs are prefixed per-document during normalization, so no conflicts -->
27+
<xsl:for-each select="$new-rdf/rdf:RDF/*[@rdf:about or @rdf:nodeID]">
28+
<xsl:variable name="id" select="(@rdf:about, @rdf:nodeID)[1]" as="xs:string"/>
29+
<xsl:if test="not(key('resources', $id, $existing-rdf))">
2830
<xsl:apply-templates select="." mode="#current"/>
2931
</xsl:if>
3032
</xsl:for-each>
3133
</xsl:copy>
3234
</xsl:template>
3335

34-
<!-- Merge new properties into existing rdf:Description -->
35-
<xsl:template match="rdf:Description" mode="ldh:MergeRDF">
36+
<!-- Merge new properties into existing URI-identified rdf:Description -->
37+
<xsl:template match="rdf:Description[@rdf:about]" mode="ldh:MergeRDF">
3638
<xsl:param name="new-rdf" as="document-node()" tunnel="yes"/>
3739

3840
<xsl:copy>

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/normalize-rdfxml.xsl

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,32 @@
4545

4646
<xsl:message>Third pass (resolve URIs) complete</xsl:message>
4747

48-
<xsl:sequence select="$resolved-rdf"/>
48+
<!-- Fourth pass: prefix all blank node IDs with a document-unique prefix to prevent conflicts when merging multiple documents -->
49+
<xsl:variable name="bnode-prefix" select="generate-id(.) || '_'" as="xs:string"/>
50+
<xsl:variable name="prefixed-rdf" as="document-node()">
51+
<xsl:document>
52+
<xsl:apply-templates select="$resolved-rdf/rdf:RDF" mode="ldh:prefix-bnodes">
53+
<xsl:with-param name="prefix" select="$bnode-prefix" tunnel="yes"/>
54+
</xsl:apply-templates>
55+
</xsl:document>
56+
</xsl:variable>
57+
58+
<xsl:sequence select="$prefixed-rdf"/>
59+
</xsl:template>
60+
61+
<!-- ========================================
62+
PASS 4: PREFIX BLANK NODE IDs
63+
======================================== -->
64+
65+
<xsl:template match="@* | node()" mode="ldh:prefix-bnodes">
66+
<xsl:copy>
67+
<xsl:apply-templates select="@* | node()" mode="#current"/>
68+
</xsl:copy>
69+
</xsl:template>
70+
71+
<xsl:template match="@rdf:nodeID" mode="ldh:prefix-bnodes">
72+
<xsl:param name="prefix" as="xs:string" tunnel="yes"/>
73+
<xsl:attribute name="rdf:nodeID" select="$prefix || ."/>
4974
</xsl:template>
5075

5176
<!-- ========================================

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -935,9 +935,10 @@ exclude-result-prefixes="#all">
935935
</xsl:apply-templates>
936936
</xsl:when>
937937
<xsl:when test="$ac:mode = '&ac;GraphMode'">
938-
<xsl:apply-templates select="." mode="bs2:Graph">
939-
<xsl:sort select="ac:label(.)"/>
940-
</xsl:apply-templates>
938+
<xsl:variable name="canvas-id" select="generate-id() || '-graph-canvas'" as="xs:string"/>
939+
<div id="{$canvas-id}" class="graph-3d-canvas"/>
940+
<div id="tooltip-{$canvas-id}" class="graph-3d-tooltip"
941+
style="display:none;position:absolute;background:rgba(0,0,0,0.75);color:#fff;padding:4px 8px;border-radius:4px;pointer-events:none;font-size:12px;z-index:10;"/>
941942
</xsl:when>
942943
<xsl:otherwise>
943944
<xsl:apply-templates select="." mode="bs2:Row">

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,18 @@ WHERE
625625
<xsl:with-param name="series" select="$series"/>
626626
</xsl:call-template>
627627
</xsl:for-each>
628+
629+
<!-- initialize 3D force graphs -->
630+
<xsl:for-each select="key('elements-by-class', 'graph-3d-canvas', ixsl:page())">
631+
<xsl:variable name="canvas-id" select="@id" as="xs:string"/>
632+
<xsl:if test="not(ixsl:contains(ixsl:get(ixsl:window(), 'LinkedDataHub.graphs'), $canvas-id))">
633+
<xsl:call-template name="ldh:InitDocumentGraph3D">
634+
<xsl:with-param name="canvas" select="."/>
635+
<xsl:with-param name="canvas-id" select="$canvas-id"/>
636+
<xsl:with-param name="rdf-doc" select="$results"/>
637+
</xsl:call-template>
638+
</xsl:if>
639+
</xsl:for-each>
628640
</xsl:for-each>
629641
</xsl:for-each>
630642
</xsl:function>

0 commit comments

Comments
 (0)