Roy Tang

Programmer, engineer, scientist, critic, gamer, dreamer, and kid-at-heart.

Blog Notes Photos Links Archives About

This is a follow-up to my question here:

So let’s say I have a number of documents structured like this:


         content: {
           name:'Joe Parent',
           children: [
               name: 'Bob Child'
               name: 'Sue Child'
               name: 'Guy Child'
       {permissions : xdmp.defaultPermissions(),
        collections : ['test']})

I want to define a template that would extract triples from these documents defining sibling relationships between the children. For the above example, I would want to extract the following triples (the relationship is two-way):

Bob Child sibling-of Sue Child
Bob Child sibling-of Guy Child
Sue Child sibling-of Bob Child
Sue Child sibling-of Guy Child
Guy Child sibling-of Bob Child
Guy Child sibling-of Sue Child

How can i set up my template to accomplish this?



I converted JSON to XML, wrote XSLT transformation to get XML triples. Later XML can be transformed back to JSON if needed.

XSLT transformation:

<xsl:stylesheet version="2.0" xmlns:xsl="" xmlns:json="" xmlns:sem="" exclude-result-prefixes="json">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="json:content">
 <sem:triples xmlns:sem="">
  <xsl:apply-templates select="json:children"/>
<xsl:template match="json:children">
 <xsl:for-each select="json:json">
  <xsl:variable name="subjectName">
   <xsl:value-of select="json:name/text()"/>
 <xsl:for-each select="following-sibling::* | preceding-sibling::* ">
    <xsl:value-of select="$subjectName"/>
   <sem:object><xsl:value-of select="json:name/text()"/></sem:object>

XQuery code that converts JSON to XML and makes transformation:

xquery version "1.0-ml";
import module namespace json = "" at "/MarkLogic/json/json.xqy";
declare namespace sem = "";
declare variable $j := '{"content": {"name": "Joe Parent","children": [{"name": "Bob Child"}, {"name": "Sue Child"}, {"name": "Guy Child"}]}}';
let $doc := json:transform-from-json($j),
$xslt := doc("myTemplates.xsl"),
$result :=  xdmp:xslt-eval($xslt,$doc),
$config := json:config("custom"),
$_ := map:put($config, "whitespace", "ignore"),
$_ := map:put($config, "array-element-names", ("triple")),
$_ := map:put($config, "element-namespace","")
return json:transform-to-json($result, $config)

I don’t know of a way to do that, but it seems like any “sibling-of” relationship is equivalent to two “child-of” relationships. Could you do something like this instead?

  ?x is-parent-of ?a-child . 
  ?x is-parent-of ?b-child. 
  ?a-child != ?b-child

Or if you’re in a position to use inference rules, you can build a rule that defines “sibling-of” like that. Then although the template doesn’t generate “sibling-of” directly, the triples are still tied to the ingested document in the same way as they would be, by virtue of the template generating the “is-parent-of” triples.