to X3D Resources
               

X3D to JSON Stylesheet Converter

               
to Web3D home page

The X3D to JSON stylesheet converts .x3d XML to .json, supporting the forthcoming JSON Encoding for X3D Graphics.

Overview | Goals | Data Types | Design Patterns | Design Correspondences | Examples | Issues | Options | References | Related Work | Tools | Contact

Status: developmental work is mature and provides full coverage. Design pattern being assessed by X3D community.


Overview to top

This work supports X3D JSON Encoding efforts by the X3D Working Group. It is summarized in the Web3D 2016 paper "A JSON Encoding for X3D".

The Web3D Consortium standards strategy has the fundamental objective to enable the open publishing of interactive 3D graphics models on the Web, enabling real-time 3D communication. Web3D carefully improves and evolves X3D Graphics and related standards while maintaining long-term archival stability.

JavaScript Object Notation (JSON) is "a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language". (from json.org)

X3D scenes can be encoded in various encoding formats. In order to consistently take advantage of JSON capabilities, the X3D Working Group is preparing a new ISO/IEC 19776-5 specification X3D JSON Encoding.

The X3D JSON Encoding needs to meet multiple interoperability requirements:

The X3D abstract specification (ISO/IEC 19775-1) governs X3D semantics and presentation for all scene encodings. Thus no new X3D functionality for graphics rendering or scene interaction are needed for the X3D JSON encoding.


Goals, Requirements and Use Cases to top

JSON defines a native JavaScript object that can be parsed directly from a JSON string. Once loaded, the resulting object tree can be used to provide a renderable presentation along with behavior of the scene graph.

Interpreting the JSON and rendering the X3D scene graph is typically an independent decision for a given JavaScript library of interest. The JSON representation is only meant to provide the scene graph for appropriate initialization in the 3D engine, and perhaps optionally export model state at a given moment if desired.

The forthcoming X3D JSON Encoding (ISO 19776-5) specification needs to fully define everything representable in a scene graph defined by the X3D Abstract Specification. Full expression of all scene graph information is commonly referred to as the "round trippable" property. This round-trippable requirement for functional equivalence is shared by all X3D encodings: XML .x3d, ClassicVRML .x3dv, Compressed Binary .x3db. Authors can thus use any X3D encoding of interest interchangeably.

Programming goals for X3D JSON include:

Note that the features for representing an entire X3D scene using JSON are quite different than the X3D language binding for ECMAScript, which describes linking or embedding JavaScript source code within a Script node as part of an X3D scene.

Functional requirements for X3D JSON include:

Use cases for X3D JSON include:


Data Types to top

JSON has two primary data structures: objects and arrays. Aligning X3D scene graphs well with these data structures is the essence of this design process. From the json.org site:

Curiously, other XML-based languages have applied multiple different approaches to mapping XML document models to JSON object models. In order to consistently reconcile conceptual overlaps, the following nomenclature conventions are been used.

Nomenclature comparison: X3D, XML, JSON
X3D scene graph XML encoding for X3D JSON encoding for X3D
X3D nodes XML elements JSON objects
X3D node name XML tag (open/close or singleton tags) JSON object name
Scene-graph structures/statements XML elements JSON objects
X3D simple-type fields XML attributes prepend @ sign to field name as JSON string
X3D MFNode child nodes Single ordered array of sibling elements One or more JSON strings for each [array of JSON objects]
X3D SFNode/MFNode field names containerField value
Example: containerField='children'
Prepend - hyphen to JSON string for field name, do not include as a separate @containerField attribute
Example: "-children"
Comments <!-- XML comment --> Special string prefix: "#comment" for single-object comments
Embedded source code for
Script, ShaderPart and ShaderProgram nodes
CDATA (Character DATA) section
<[CDATA[ "world wild Web!" ]]>
"#sourceCode" string array containing original code, typically not escaped. (previously named #sourceText)

TODO: add notes contrasting document models to object models.


Design Patterns to top

It is important to get the X3D JSON design pattern correct. Here are possible approaches for an example set of four adjacent ROUTE statements.

Source excerpts from scene OrigamiCranes.x3d
<Group DEF='AnimatedView'>
    <Viewpoint DEF='MovingPov' description='Rotating Viewpoint'/>
    <TimeSensor DEF='PovClock' cycleInterval='60' loop='true'/>
    <PositionInterpolator DEF='MovingPovLocation' key='0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1' 
                                    keyValue='0 0 3 etc.'/>
    <ROUTE fromField='fraction_changed' fromNode='PovClock' toField='set_fraction' toNode='MovingPovRotation'/>
    <ROUTE fromField='fraction_changed' fromNode='PovClock' toField='set_fraction' toNode='MovingPovLocation'/>
    <OrientationInterpolator DEF='MovingPovRotation' key='0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1' 
        keyValue='0 1 0 0 etc.'/>
    <ROUTE fromField='value_changed' fromNode='MovingPovRotation' toField='set_orientation' toNode='MovingPov'/>
    <ROUTE fromField='value_changed' fromNode='MovingPovLocation' toField='position' toNode='MovingPov'/>
</Group>

For comparison, please look at the different approaches that follow. Each pattern encodes these same four ROUTEs.

The pattern on the left is important from a JSON perspective, because it avoids JSON validation errors. This is because it avoids object-model ambiguity problems that occur when multiple key names are repeated for a parent object.

The pattern in the third column (showing the four ROUTEs in context) was evaluated as the best solution for preserving ROUTE ordering within an X3D scene.

Single key for contained objects:
valid JSON
Repeating keys for multiple objects:
invalid JSON
Common -children key for ROUTE objects:
valid JSON. Approved.
"ROUTE":[
  {
    "@fromField":"fraction_changed",
    "@fromNode":"PovClock",
    "@toField":"set_fraction",
    "@toNode":"MovingPovRotation"
  },
  {
    "@fromField":"fraction_changed",
    "@fromNode":"PovClock",
    "@toField":"set_fraction",
    "@toNode":"MovingPovLocation"
  },
  {
    "@fromField":"value_changed",
    "@fromNode":"MovingPovRotation",
    "@toField":"set_orientation",
    "@toNode":"MovingPov"
  },
  {
    "@fromField":"value_changed",
    "@fromNode":"MovingPovLocation",
    "@toField":"position",
    "@toNode":"MovingPov"
  }
]

Advantages: terse, clear.

Disadvantages: ordering of ROUTE statements is lost, relative to other children nodes. ROUTEs are placed at the end, only a partial order is retained.

The downside of bundling the four ROUTEs together is that these statements might not have appeared side-by-side in the original X3D scene. The order of the sequence from first to last might be unchanged, but these ROUTE statements might appear before & after other nodes when compared to the original scene.

For this approach, moving ROUTEs means that exact literal round-trippability with the original scene is not always possible. Nevertheless functional equivalence of rendering and behavior for the scene appears to be possible. Local partial sorts can limit any reshuffling to sorting by field, leaving the original first-to-last sequence of occurrence unchanged.

"ROUTE":
  {
    "@fromField":"fraction_changed",
    "@fromNode":"PovClock",
    "@toField":"set_fraction",
    "@toNode":"MovingPovRotation"
  },
"ROUTE":
  {
    "@fromField":"fraction_changed",
    "@fromNode":"PovClock",
    "@toField":"set_fraction",
    "@toNode":"MovingPovLocation"
  },
"ROUTE":
  {
    "@fromField":"value_changed",
    "@fromNode":"MovingPovRotation",
    "@toField":"set_orientation",
    "@toNode":"MovingPov"
  },
"ROUTE":
  {
    "@fromField":"value_changed",
    "@fromNode":"MovingPovLocation",
    "@toField":"position",
    "@toNode":"MovingPov"
  }

Advantages: terse, clear.

Disadvantages: invalid JSON object since the ROUTE key is used multiple times.

{ "Group":
  {
    "@DEF":"AnimatedView",
    "-children":[
      { "Viewpoint":
        {
          "@DEF":"MovingPov",
          "@description":"Rotating Viewpoint"
        }
      },
      { "TimeSensor":
        {
          "@DEF":"PovClock",
          "@cycleInterval":60,
          "@loop":true
        }
      },
      { "PositionInterpolator":
        {
          "@DEF":"MovingPovLocation",
          "@key":[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1],
          "@keyValue":[0,0,3,3,0,2,3,0,2,0,0,3,0,0,3,-3,0,2,-3,0,2,0,0,3,0,0,3]
        }
      },
      { "ROUTE":
        {
          "@fromField":"fraction_changed",
          "@fromNode":"PovClock",
          "@toField":"set_fraction",
          "@toNode":"MovingPovLocation"
        }
      },
      { "ROUTE":
        {
          "@fromField":"value_changed",
          "@fromNode":"MovingPovLocation",
          "@toField":"position",
          "@toNode":"MovingPov"
        }
      },
      { "OrientationInterpolator":
        {
          "@DEF":"MovingPovRotation",
          "@key":[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1],
          "@keyValue":[0,1,0,0,0,1,0,0.982794,etc.]
        }
      },
      { "ROUTE":
        {
          "@fromField":"fraction_changed",
          "@fromNode":"PovClock",
          "@toField":"set_fraction",
          "@toNode":"MovingPovRotation"
        }
      },
      { "ROUTE":
        {
          "@fromField":"value_changed",
          "@fromNode":"MovingPovRotation",
          "@toField":"set_orientation",
          "@toNode":"MovingPov"
        }
      }
    ]
  }
},

Advantages: terse, clear. Ordering of nodes in the original scene is nearly always preserved.

Some special X3D semantics must always be observed. For example, X3D requires each ROUTE must appear after the DEF nodes it refers to. (DEF/USE name identifiers for X3D nodes have type ID/IDREF in XML, which does not provide ordering constraints.) Preserving order with other peer nodes avoids creating any new problems for a scene.

Typically most elements are children nodes, but that is not always the case. Since a ROUTE is allowed to appear almost anywhere in the scene graph, one extra precaution is necessary. For acceptable local reordering of ROUTEs that appear within a Shape, or within other nodes that are outside of a regular -children context, the "-children":{ROUTE} constructs are placed after any other sibling nodes.


Design Correspondences to top

These design patterns for X3D JSON include the following correspondences.

See the Issues list for additional changes under consideration.

The following tables illustrate how each of the major JSON constructs are correlated to X3D nodes, fields, statements and values.

JSON objects to top

JSON objects are typically an X3D node, or scene graph structure element. Note that each string matches an X3D field name and must be unique, allowing direct access to each field.

string : value
X3D, head and Scene : scene-graph structure elements
simple-type field name : attribute value
containerField : X3D nodes (XML elements) as JSON objects

JSON arrays to top

X3D scene graph JSON representation of value
X3DGrouping nodes: MFNode children array array of JSON objects
Scene and ProtoBody elements: MFNode children array array of JSON objects
MFBool array of simple SFBool values (XML attribute): JSON array of boolean (true|false) values
MFInt32 array of simple SFInt32 values (XML attribute): JSON array of number type with non-decimal values
MFFloat/MFDouble array of simple SFFloat/SFDouble values (XML attribute): JSON array of number type with decimal values
SFVec*/MFVec* n-tuple arrays of SFFloat/SFDouble values (XML attribute): JSON array of number type with decimal values
SFColor/MFColor and SFColorRGBA/MFColorRGBA triplet arrays of SFFloat/SFDouble values (XML attribute): JSON array of number type with decimal values, range [0..1]
MFString is array of quoted SFString (XML attribute) values JSON array of string type

JSON values to top

X3D scene graph JSON representation of value
SFString simple type (XML attribute) JSON value of string type, no added "quote marks"
SFInt32 simple type (XML attribute) JSON value of number type, no decimal point
SFFloat/SFDouble simple type (XML attribute) JSON value of number type, with
leading numeral(s) and decimal point
SFBool simple type (XML attribute) JSON value of boolean type (true|false)
SFNode field (XML element) JSON value of object type or null (no entry)
MFNode field (array XML elements)
each having identical containerField values
JSON array of object types
each sharing identical string key

JSON strings to top

X3D scene graph JSON representation
SFString is unquoted XML attribute value JSON value of string type. Backslash \ (reverse solidus) characters get escaped with an adjacent backslash \ character, resulting in \\ value.
Similarly " (quotation mark) characters get escaped with an adjacent backslash as \" value.
MFString is array of quoted SFString (XML attribute) values JSON array of string type

JSON numbers to top

X3D scene graph JSON representation
Numeric attributes with type SF/MFFloat, SF/MFDouble, SF/MFVec*,SF/MFMatrix* integer or floating point with double precision;
note that leading zero required if less than zero;
note no scientific notation (e.g. 1.0E-6);
note no leading + plus sign allowed
SFBool/MFBool boolean (true, false)

 Examples Examples list to top

Test examples are essential for determining how the X3D JSON encoding can best meets authoring and library requirements.

Excerpted encodings of example X3D scene-graph fragments follow.

TODO: show continued conversion excerpts including nodes, attributes, comments, children nodes, X3D statements, Scripts, prototypes, fields, IS/connect.

X3D file structure to Examples list

Source excerpts, .x3d and .json Notes
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "https://www.web3d.org/specifications/x3d-3.3.dtd">
<X3D 
  profile='Immersive' version='3.3
  xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance'
  xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'>
    <head></head>
    <Scene></Scene>
</X3D>

X3D, head and Scene are scene-graph structure statements.

X3D @profile and @version attributes are required.

X3D @xmlns:xsd and @xsd:noNamespaceSchemaLocation attributes are optional.

 { "X3D": {
      "@profile":"Immersive",
      "@version":3.3,
      "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.3.xsd",
      "head":{
      },
      "Scene":{
      }
    }
 }

XML header and DOCTYPE are omitted in the JSON encoding.

X3D, head and Scene are JSON objects that contain arrays of JSON objects.

Resolved: avoid wrapping the X3D object in [array brackets] since they are superfluous.

X3D head excerpt to Examples list

Source excerpts, .x3d and .json Notes
  <head>
    <component level='1' name='CADGeometry'/>
    <component level='1' name='HAnim'/>
    <unit category='length' conversionFactor='0.9144' name='Yards'/>
    <unit category='angle' conversionFactor='0.0174532925167' name='Degrees'/>
    <meta content='TestJsonEncoding.x3d' name='title'/>
    <meta content='2 November 2015' name='modified'/>
    <meta content='TestJsonEncoding.json' name='reference'/>
    <!-- Here is a comment. -->
  </head>

Note that this excerpt from an X3D scene only produces a valid JSON fragment because it does not include the parent X3D element.

 { "X3D": {
   "head":{
      { "component":[
        {
          "@level":1,
          "@name":"CADGeometry"
        },
        {
          "@level":1,
          "@name":"HAnim"
        }
      ]
      },
      { "unit":[
        {
          "@category":"length",
          "@conversionFactor":0.9144,
          "@name":"Yards"
        },
        {
          "@category":"angle",
          "@conversionFactor":0.0174532925167,
          "@name":"Degrees"
        }
      ]
      },
      { "meta":[
        {
          "@content":"TestJsonEncoding.x3d",
          "@name":"title"
        },
        {
          "@content":"2 November 2015",
          "@name":"modified"
        },
        {
          "@content":"TestJsonEncoding.json",
          "@name":"reference"
        }
      ]
      },
      { "#comment":"Here is a comment."
      }
    }
  }

Note multiple statement elements are collected as objects, with each set of matching objects found under a single statement key.

Comments are treated as -children objects, typically allowing them to appear individually instead of clumped under a single key.

Hello World Example to Examples list

Source excerpts, .x3d and .json Notes
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "https://www.web3d.org/specifications/x3d-3.3.dtd">
<X3D profile='Immersive' version='3.3'
   xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' 
   xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'>
  <head>
    <meta content='HelloWorld.x3d' name='title'/>
    <meta content='Simple X3D scene example: Hello World!' name='description'/>
    <meta content='30 October 2000' name='created'/>
    <meta content='14 October 2015' name='modified'/>
    <meta content='Don Brutzman' name='creator'/>
    <meta content='HelloWorld.tall.png' name='Image'/>
    <meta content='http://en.wikipedia.org/wiki/Hello_world' name='reference'/>
    <meta content='https://en.wikipedia.org/wiki/Hello#.22Hello.2C_World.22_computer_program' name='reference'/>
    <meta content='https://en.wikipedia.org/wiki/"Hello,_World!"_program' name='reference'/>
    <meta content='http://en.wikibooks.org/w/index.php?title=Computer_Programming/Hello_world' name='reference'/>
    <meta content='http://www.HelloWorldExample.net' name='reference'/>
    <meta content='http://www.web3D.org' name='reference'/>
    <meta content='https://www.web3d.org/realtime-3d/news/internationalization-x3d' name='reference'/>
    <meta content='https://www.web3d.org/x3d/content/examples/HelloWorld.x3d' name='reference'/>
    <meta content='http://X3dGraphics.com/examples/X3dForAdvancedModeling/HelloWorldScenes' name='reference'/>
    <meta content='http://X3dGraphics.com/examples/X3dForWebAuthors/Chapter01-TechnicalOverview/HelloWorld.x3d' 
          name='identifier'/>
    <meta content='https://www.web3d.org/x3d/content/examples/license.html' name='license'/>
    <meta content='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit' name='generator'/>
    <!-- Alternate encodings: VRML97, X3D ClassicVRML Encoding, X3D Compressed Binary Encoding (CBE), X3DOM, JSON -->
    <meta content='HelloWorld.wrl' name='reference'/>
    <meta content='HelloWorld.x3dv' name='reference'/>
    <meta content='HelloWorld.x3db' name='reference'/>
    <meta content='HelloWorld.xhtml' name='reference'/>
    <meta content='HelloWorld.json' name='reference'/>
  </head>
  <Scene>
    <!-- Example scene to illustrate X3D nodes and fields (XML elements and attributes) -->
    <WorldInfo title='Hello world!'/>
    <Group>
      <Viewpoint DEF='ViewUpClose' centerOfRotation='0 -1 0' description='Hello world!' position='0 -1 7'/>
      <Transform rotation='0 1 0 3'>
        <Shape>
          <Sphere/>
          <Appearance>
            <Material DEF='MaterialLightBlue' diffuseColor='0.1 0.5 1'/>
            <ImageTexture  DEF='ImageCloudlessEarth' 
                                url='"earth-topo.png" "earth-topo.jpg" "earth-topo-small.gif" 
                                     "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.png" 
                                     "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.jpg" 
                                     "https://www.web3d.org/x3d/content/examples/Basic/earth-topo-small.gif"'/>
          </Appearance>
        </Shape>
      </Transform>
      <Transform translation='0 -2 0'>
        <Shape>
          <Text  DEF='TextMessage' string='"Hello" "world!"'>
            <FontStyle  justify='"MIDDLE" "MIDDLE"'/>
         </Text>
          <Appearance>
            <Material USE='MaterialLightBlue'/>
          </Appearance>
        </Shape>
      </Transform>
    </Group>
  </Scene>
</X3D>

HelloWorld.x3d source,
HelloWorld.html pretty-print, and
HelloWorld.xhtml using X3DOM

Source excerpts, .x3d and .json Notes to Examples list
{ "X3D": {
    "encoding":"UTF-8",
    "@profile":"Immersive",
    "@version":"3.3",
    "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.3.xsd",
    "JSON schema":"https://www.web3d.org/specifications/x3d-3.3-JSONSchema.json",
    "head": {
        "meta": [
          {
            "@name":"title",
            "@content":"HelloWorld.x3d"
          },
          {
            "@name":"description",
            "@content":"Simple X3D scene example: Hello World!"
          },
          {
            "@name":"created",
            "@content":"30 October 2000"
          },
          {
            "@name":"modified",
            "@content":"23 November 2014"
          },
          {
            "@name":"creator",
            "@content":"Don Brutzman"
          },
          {
            "@name":"Image",
            "@content":"HelloWorld.tall.png"
          },
          {
            "@name":"reference",
            "@content":"http://en.wikipedia.org/wiki/Hello_world"
          },
          {
            "@name":"reference",
            "@content":"en.wikipedia.org/wiki/Hello#\"Hello,_World\"_computer_program"
          },
          {
            "@name":"reference",
            "@content":"http://en.wikibooks.org/w/index.php?title=Computer_Programming/Hello_world"
          },
          {
            "@name":"reference",
            "@content":"http://www.HelloWorldExample.net"
          },
          {
            "@name":"reference",
            "@content":"http://www.web3D.org"
          },
          {
            "@name":"reference",
            "@content":"https://www.web3d.org/realtime-3d/news/internationalization-x3d"
          },
          {
            "@name":"reference",
            "@content":"https://www.web3d.org/x3d/content/examples/HelloWorld.x3d"
          },
          {
            "@name":"reference",
            "@content":"http://X3dGraphics.com/examples/X3dForAdvancedModeling/HelloWorldScenes"
          },
          {
            "@name":"identifier",
            "@content":"http://X3dGraphics.com/examples/X3dForWebAuthors/Chapter01-TechnicalOverview/HelloWorld.x3d"
          },
          {
            "@name":"license",
            "@content":"https://www.web3d.org/x3d/content/examples/license.html"
          },
          {
            "@name":"generator",
            "@content":"X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit"
          },
          {
            "@name":"reference",
            "@content":"HelloWorld.wrl"
          },
          {
            "@name":"reference",
            "@content":"HelloWorld.x3dv"
          },
          {
            "@name":"reference",
            "@content":"HelloWorld.x3db"
          },
          {
            "@name":"reference",
            "@content":"HelloWorld.xhtml"
          },
          {
            "@name":"reference",
            "@content":"HelloWorld.json"
          },
          {
            "@name":"translated",
            "@content":"17 March 2016"
          },
          {
            "@name":"generator",
            "@content":"X3dToJson.xslt, https://www.web3d.org/x3d/stylesheets/X3dToJson.html"
          },
          {
            "@name":"warning",
            "@content":"An experimental version of X3D JSON encoding is used for this scene.
                        Status online at https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding"
          }
        ],
        "-children":[
          { "#comment":"Alternate encodings: VRML97, X3D ClassicVRML Encoding, 
             X3D Compressed Binary Encoding (CBE), X3DOM, JSON"
          }
        ]
    },
    "Scene": {
        "-children":[
          { "#comment":"Example scene to illustrate X3D nodes and fields (XML elements and attributes)"
          },
          { "Group":
            {
              "-children":[
                { "Viewpoint":
                  {
                    "@DEF":"ViewUpClose",
                    "@centerOfRotation":[0,-1,0],
                    "@description":"Hello world!",
                    "@position":[0,-1,7]
                  }
                },
                { "Transform":
                  {
                    "@rotation":[0,1,0,3],
                    "-children":[
                      { "Shape":
                        {
                          "-geometry":
                            { "Sphere":
                              {
                              }
                            },
                          "-appearance":
                            { "Appearance":
                              {
                                "-material":
                                  { "Material":
                                    {
                                      "@DEF":"MaterialLightBlue",
                                      "@diffuseColor":[0.1,0.5,1]
                                    }
                                  },
                                "-texture":
                                  { "ImageTexture":
                                    {
                                      "@DEF":"ImageCloudlessEarth",
                                      "@url":[
"earth-topo.png","earth-topo.jpg","earth-topo-small.gif",
"https://www.web3d.org/x3d/content/examples/Basic/earth-topo.png",
"https://www.web3d.org/x3d/content/examples/Basic/earth-topo.jpg",
"https://www.web3d.org/x3d/content/examples/Basic/earth-topo-small.gif"]
                                    }
                                  }
                              }
                            }
                        }
                      }
                    ]
                  }
                },
                { "Transform":
                  {
                    "@translation":[0,-2,0],
                    "-children":[
                      { "Shape":
                        {
                          "-geometry":
                            { "Text":
                              {
                                "@DEF":"TextMessage",
                                "@string":["Hello","world!"],
                                "-fontStyle":
                                  { "FontStyle":
                                    {
                                      "@justify":["MIDDLE","MIDDLE"]
                                    }
                                  }
                              }
                            },
                          "-appearance":
                            { "Appearance":
                              {
                                "-material":
                                  { "Material":
                                    {
                                      "@USE":"MaterialLightBlue"
                                    }
                                  }
                              }
                            }
                        }
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
    }
  }
}

HelloWorld.json

Comments are treated as a unique-key array of objects, which appears before other child elements.

Attributes with default values are omitted for clarity.

Line breaks inserted in url arrays for readability.

Test Json Encoding Example to Examples list

Source excerpts, .x3d and .json Notes
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN"  "https://www.web3d.org/specifications/x3d-3.3.dtd">
<X3D profile='Immersive' version='3.3' 
    xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' 
    xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'>
  <head>
    <component level='1' name='CADGeometry'/>
    <component level='1' name='HAnim'/>
    <unit category='length' conversionFactor='0.9144' name='Yards'/>
    <unit category='angle' conversionFactor='0.0174532925167' name='Degrees'/>
    <meta content='TestJsonEncoding.x3d' name='title'/>
    <meta content='Don Brutzman' name='creator'/>
    <meta content='29 March 2015' name='created'/>
    <meta content='3 November 2015' name='modified'/>
    <meta content='Test scene to ensure that X3dToJson xslt stylesheet translator properly converts X3D source
          into JavaScript Object Notation (JSON).' name='description'/>
    <meta content='TestJsonEncoding.json' name='reference'/>
    <meta content='https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding' name='reference'/>
    <meta content='https://www.web3d.org/x3d/content/examples/Basic/development/TestJsonEncoding.x3d' 
          name='identifier'/>
    <meta content='https://www.web3d.org/x3d/stylesheets/X3dToJson.xslt' name='reference'/>
    <meta content='https://www.web3d.org/x3d/stylesheets/X3dToJson.html' name='reference'/>
    <meta content='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit' name='generator'/>
    <meta content='../license.html' name='license'/>
  </head>
  <Scene>
    <!-- excerpted from HelloWorld.x3d -->
    <Group>
      <Viewpoint DEF='ViewUpClose' centerOfRotation='0 -1 0' description='Hello world!' position='0 -1 7'/>
      <Transform rotation='0 1 0 3'>
        <Shape>
          <Sphere/>
          <Appearance>
            <!-- Test leading zeroes inserted before (and trailing zeroes inserted after) decimal points:
                  diffuseColor='.1 0.5 1.' -->
            <Material DEF='MaterialLightBlue' diffuseColor='.1 0.5 1.'/>
            <ImageTexture  DEF='ImageCloudlessEarth' 
                                     url='"earth-topo.png" "earth-topo.jpg" "earth-topo-small.gif" 
                                          "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.png"
                                          "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.jpg" 
                                          "https://www.web3d.org/x3d/content/examples/Basic/earth-topo-small.gif"'/>
          </Appearance>
        </Shape>
      </Transform>
      <Transform translation='-.1 -2 -.2'>
        <!-- Test leading zeroes inserted between -. values: translation='-.1 -2 -.2' -->
        <Shape>
          <Text  DEF='TextMessage' string='"Hello" "JSON!"'>
            <FontStyle  justify='"MIDDLE" "MIDDLE"'/>
         </Text>
          <Appearance>
            <Material USE='MaterialLightBlue'/>
          </Appearance>
        </Shape>
      </Transform>
    </Group>
  </Scene>
</X3D>

TestJsonEncoding.x3d source,
TestJsonEncoding.html pretty-print, and
TestJsonEncoding.xhtml using X3DOM

Source excerpts, .x3d and .json Notes to Examples list
{ "X3D": {
    "encoding":"UTF-8",
    "@profile":"Immersive",
    "@version":"3.3",
    "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.3.xsd",
    "JSON schema":"https://www.web3d.org/specifications/x3d-3.3-JSONSchema.json",
    "head": {
        "component": [
          {
            "@name":"CADGeometry",
            "@level":1
          },
          {
            "@name":"HAnim",
            "@level":1
          }
        ],
        "unit": [
          {
            "@name":"Yards",
            "@category":"length",
            "@conversionFactor":0.9144
          },
          {
            "@name":"Degrees",
            "@category":"angle",
            "@conversionFactor":0.0174532925167
          }
        ],
        "meta": [
          {
            "@name":"title",
            "@content":"TestJsonEncoding.x3d"
          },
          {
            "@name":"creator",
            "@content":"Don Brutzman"
          },
          {
            "@name":"created",
            "@content":"29 March 2015"
          },
          {
            "@name":"modified",
            "@content":"3 November 2015"
          },
          {
            "@name":"description",
            "@content":"Test scene to ensure that X3dToJson xslt stylesheet translator
                        properly converts X3D source into JavaScript Object Notation (JSON)."
          },
          {
            "@name":"reference",
            "@content":"TestJsonEncoding.json"
          },
          {
            "@name":"reference",
            "@content":"https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding"
          },
          {
            "@name":"identifier",
            "@content":"https://www.web3d.org/x3d/content/examples/Basic/development/TestJsonEncoding.x3d"
          },
          {
            "@name":"reference",
            "@content":"https://www.web3d.org/x3d/stylesheets/X3dToJson.xslt"
          },
          {
            "@name":"reference",
            "@content":"https://www.web3d.org/x3d/stylesheets/X3dToJson.html"
          },
          {
            "@name":"generator",
            "@content":"X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit"
          },
          {
            "@name":"license",
            "@content":"../license.html"
          },
          {
            "@name":"translated",
            "@content":"17 March 2016"
          },
          {
            "@name":"generator",
            "@content":"X3dToJson.xslt, https://www.web3d.org/x3d/stylesheets/X3dToJson.html"
          },
          {
            "@name":"warning",
            "@content":"An experimental version of X3D JSON encoding is used for this scene.
                        Status online at https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding"
          }
        ]
    },
    "Scene": {
        "-children":[
          { "#comment":"excerpted from HelloWorld.x3d"
          },
          { "Group":
            {
              "-children":[
                { "Viewpoint":
                  {
                    "@DEF":"ViewUpClose",
                    "@centerOfRotation":[0,-1,0],
                    "@description":"Hello world!",
                    "@position":[0,-1,7]
                  }
                },
                { "Transform":
                  {
                    "@rotation":[0,1,0,3],
                    "-children":[
                      { "Shape":
                        {
                          "-geometry":
                            { "Sphere":
                              {
                              }
                            },
                          "-appearance":
                            { "Appearance":
                              {
                                "-children":[
                                  { "#comment":"Test leading zeroes inserted before 
                                        (and trailing zeroes inserted after) decimal points: diffuseColor='.1 0.5 1.'"
                                  }
                                ],
                                "-material":
                                  { "Material":
                                    {
                                      "@DEF":"MaterialLightBlue",
                                      "@diffuseColor":[0.1,0.5,1.0]
                                    }
                                  },
                                "-texture":
                                  { "ImageTexture":
                                    {
                                      "@DEF":"ImageCloudlessEarth",
                                      "@url":[
"earth-topo.png","earth-topo.jpg","earth-topo-small.gif",
"https://www.web3d.org/x3d/content/examples/Basic/earth-topo.png",
"https://www.web3d.org/x3d/content/examples/Basic/earth-topo.jpg",
"https://www.web3d.org/x3d/content/examples/Basic/earth-topo-small.gif"]
                                    }
                                  }
                              }
                            }
                        }
                      }
                    ]
                  }
                },
                { "Transform":
                  {
                    "@translation":[-0.1,-2,-0.2],
                    "-children":[
                      { "#comment":"Test leading zeroes inserted between -. values: translation='-.1 -2 -.2'"
                      },
                      { "Shape":
                        {
                          "-geometry":
                            { "Text":
                              {
                                "@DEF":"TextMessage",
                                "@string":["Hello","JSON!"],
                                "-fontStyle":
                                  { "FontStyle":
                                    {
                                      "@justify":["MIDDLE","MIDDLE"]
                                    }
                                  }
                              }
                            },
                          "-appearance":
                            { "Appearance":
                              {
                                "-material":
                                  { "Material":
                                    {
                                      "@USE":"MaterialLightBlue"
                                    }
                                  }
                              }
                            }
                        }
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
    }
  }
}

TestJsonEncoding.json

Comments are treated as a unique-key array of objects, which appears before other child elements.

Attributes with default values are omitted for clarity.

Line breaks inserted in url arrays for readability.

Origami Cranes Example to Examples list

Source excerpts, .x3d and .json Notes
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "https://www.web3d.org/specifications/x3d-3.3.dtd">
<X3D profile='Interactive' version='3.3'
     xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance'
     xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'>
  <head>
    <meta content='OrigamiCranes.x3d' name='title'/>
    <meta content='Origami Cranes with black/white contrast as art work for Black Swan game.'
       name='description'/>
    <meta content='2 November 2014' name='created'/>
    <meta content='3 November 2015' name='modified'/>
    <meta content='epicpopcorn' name='creator'/>
    <meta content='http://www.turbosquid.com/FullPreview/Index.cfm/ID/598176' name='reference'/>
    <meta content='crane.obj' name='reference'/>
    <meta content='OrigamiCrane.ply' name='reference'/>
    <meta content='Don Brutzman' name='translator'/>
    <meta content='http://en.wikipedia.org/wiki/Swan' name='reference'/>
    <meta content='http://en.wikipedia.org/wiki/Orizuru' name='reference'/>
    <meta content='http://www.youtube.com/watch?v=CXwwPgMiEPc' name='reference'/>
    <meta content='http://www.origami-make.com/howto-origami-swan.php' name='reference'/>
    <meta content='http://origami.about.com/od/Origami-Animals/tp/How-To-Make-An-Origami-Swan.htm' 
        name='reference'/>
    <meta content='http://en.wikipedia.org/wiki/The_Black_Swan_(2007_book)' name='reference'/>
    <meta content='http://en.wikipedia.org/wiki/Nassim_Nicholas_Taleb' name='reference'/>
    <meta content='Making sense of The Black Swan por Mark Crovelli, quarta-feira, 18 de abril de 2012' 
        name='reference'/>
    <meta content='http://www.mises.org.br/Article.aspx?id=1284' name='reference'/>
    <meta content='http://www.mises.org.br/images/articles/2012/Abril/black_swan.jpg' name='Image'/>
    <meta content='OrigamiBlackSwanWhiteSwan.jpg' name='Image'/>
    <meta content='http://x3dGraphics.com/examples/X3dForAdvancedModeling/Animation/OrigamiCranes.x3d' 
               name='identifier'/>
    <meta content='OrigamiCraneMeshlab.png' name='Image'/>
    <meta content='Meshlab X3D Exported, http://meshlab.sourceforge.net' name='generator'/>
    <meta content='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit' name='generator'/>
    <meta content='http://support.turbosquid.com/entries/31030006-Royalty-Free-License?locale=1' 
        name='license'/>
    <meta content='../license.html' name='license'/>
  </head>
  <Scene>
    <Background groundAngle='1.5707' groundColor='1 1 1 1 1 1' skyAngle='0' skyColor='0 0 0 0 0 0'/>
    <NavigationInfo type='"NONE"'/>
    <PointLight intensity='0.3' location='0 2 6'/>
    <PointLight intensity='0.3' location='0 -2 6'/>
    <Group DEF='AnimatedView'>
      <Viewpoint DEF='MovingPov' description='Rotating Viewpoint'/>
      <TimeSensor DEF='PovClock' cycleInterval='60' loop='true'/>
      <PositionInterpolator DEF='MovingPovLocation' key='0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1' 
        keyValue='0 0 3 3 0 2 3 0 2 0 0 3 0 0 3 -3 0 2 -3 0 2 0 0 3 0 0 3'/>   
      <ROUTE fromField='fraction_changed' fromNode='PovClock' toField='set_fraction' toNode='MovingPovLocation'/>
      <ROUTE fromField='value_changed' fromNode='MovingPovLocation' toField='position' toNode='MovingPov'/>
      <OrientationInterpolator DEF='MovingPovRotation' key='0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1' 
        keyValue='0 1 0 0 0 1 0 0.982794 0 1 0 0.982794 0 1 0 0 0 1 0 0 0 1 0 -0.982794 0 1 0 -0.982794
                  0 1 0 0 0 1 0 0'/>
      <ROUTE fromField='fraction_changed' fromNode='PovClock' toField='set_fraction' toNode='MovingPovRotation'/>
      <ROUTE fromField='value_changed' fromNode='MovingPovRotation' toField='set_orientation' toNode='MovingPov'/>
    </Group>
    <Viewpoint description='Origami Cranes, from ahead' orientation='0 1 0 0.982794' position='3 0 2'/>
    <Viewpoint description='Origami Cranes, mirror image' position='0 0 3'/>
    <Viewpoint description='Origami Cranes, from behind' orientation='0 1 0 -0.982794' position='-3 0 2'/>
    <Transform DEF='CraneAbove' rotation='0 1 0 1.745329'>
      <!-- Rotation was necessary to point along X axis -->
      <Transform DEF='TranslateToOrigin' translation='0.25 -0.18 -0.1'>
        <Shape DEF='CraneShapeWhite'>
          <IndexedFaceSet DEF='CraneIFS' coordIndex='0 1 2 -1 0 2 3 -1 4 5 2 -1  [... omitted ...]'
                                    solid='false'>
            <!-- Original model values are quite large, converted from inches to meters using factor 0.0254 to rescale, 
                  wingtip is now 0.8m and length is 1.5m. -->
            <Coordinate point='-0.39882 0.8134 0.63626 -0.33169 0.81323 0.53558 [... omitted ...]'/>
          </IndexedFaceSet>
          <Appearance> 
            <Material diffuseColor='0.9 0.9 0.9'/>
          </Appearance>
        </Shape>
      </Transform>
    </Transform>
    <Transform DEF='CraneBelow' rotation='1 0 0 3.141593'>
      <Transform rotation='0 1 0 1.745329'>
        <Transform translation='0.25 -0.18 -0.1'>
          <Shape DEF='CraneShapeBlack'>
            <IndexedFaceSet USE='CraneIFS'/>
            <Appearance>
              <Material diffuseColor='0.15 0.15 0.15'/>
            </Appearance>
          </Shape>
        </Transform>
      </Transform>
    </Transform>
  </Scene>
</X3D>

OrigamiCranes.x3d source,
OrigamiCranes.html pretty-print, and
OrigamiCranes.xhtml using X3DOM

Source excerpts, .x3d and .json Notes to Examples list
{ "X3D": {
    "encoding":"UTF-8",
    "@profile":"Interactive",
    "@version":"3.3",
    "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.3.xsd",
    "JSON schema":"https://www.web3d.org/specifications/x3d-3.3-JSONSchema.json",
    "head": {
        "meta": [
          {
            "@name":"title",
            "@content":"OrigamiCranes.x3d"
          },
          {
            "@name":"description",
            "@content":"Origami Cranes with black/white contrast as art work for Black Swan game."
          },
          {
            "@name":"created",
            "@content":"2 November 2014"
          },
          {
            "@name":"modified",
            "@content":"11 November 2015"
          },
          {
            "@name":"creator",
            "@content":"epicpopcorn"
          },
          {
            "@name":"reference",
            "@content":"http://www.turbosquid.com/FullPreview/Index.cfm/ID/598176"
          },
          {
            "@name":"reference",
            "@content":"crane.obj"
          },
          {
            "@name":"reference",
            "@content":"OrigamiCrane.ply"
          },
          {
            "@name":"translator",
            "@content":"Don Brutzman"
          },
          {
            "@name":"reference",
            "@content":"http://en.wikipedia.org/wiki/Swan"
          },
          {
            "@name":"reference",
            "@content":"http://en.wikipedia.org/wiki/Orizuru"
          },
          {
            "@name":"reference",
            "@content":"http://www.youtube.com/watch?v=CXwwPgMiEPc"
          },
          {
            "@name":"reference",
            "@content":"http://www.origami-make.com/howto-origami-swan.php"
          },
          {
            "@name":"reference",
            "@content":"http://origami.about.com/od/Origami-Animals/tp/How-To-Make-An-Origami-Swan.htm"
          },
          {
            "@name":"reference",
            "@content":"http://en.wikipedia.org/wiki/The_Black_Swan_(2007_book)"
          },
          {
            "@name":"reference",
            "@content":"http://en.wikipedia.org/wiki/Nassim_Nicholas_Taleb"
          },
          {
            "@name":"reference",
            "@content":"Making sense of The Black Swan por Mark Crovelli, quarta-feira, 18 de abril de 2012"
          },
          {
            "@name":"reference",
            "@content":"http://www.mises.org.br/Article.aspx?id=1284"
          },
          {
            "@name":"Image",
            "@content":"http://www.mises.org.br/images/articles/2012/Abril/black_swan.jpg"
          },
          {
            "@name":"Image",
            "@content":"OrigamiBlackSwanWhiteSwan.jpg"
          },
          {
            "@name":"identifier",
            "@content":"http://x3dGraphics.com/examples/X3dForAdvancedModeling/Animation/OrigamiCranes.x3d"
          },
          {
            "@name":"Image",
            "@content":"OrigamiCraneMeshlab.png"
          },
          {
            "@name":"generator",
            "@content":"Meshlab X3D Exported, http://meshlab.sourceforge.net"
          },
          {
            "@name":"generator",
            "@content":"X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit"
          },
          {
            "@name":"license",
            "@content":"http://support.turbosquid.com/entries/31030006-Royalty-Free-License?locale=1"
          },
          {
            "@name":"license",
            "@content":"../license.html"
          },
          {
            "@name":"translated",
            "@content":"17 March 2016"
          },
          {
            "@name":"generator",
            "@content":"X3dToJson.xslt, https://www.web3d.org/x3d/stylesheets/X3dToJson.html"
          },
          {
            "@name":"warning",
            "@content":"An experimental version of X3D JSON encoding is used for this scene
                        Status online at https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding"
          }
        ]
    },
    "Scene": {
        "-children":[
          { "Background":
            {
              "@groundAngle":[1.5707],
              "@groundColor":[1,1,1,1,1,1],
              "@skyAngle":[0],
              "@skyColor":[0,0,0,0,0,0]
            }
          },
          { "NavigationInfo":
            {
              "@type":["NONE"]
            }
          },
          { "PointLight":
            {
              "@intensity":0.3,
              "@location":[0,2,6]
            }
          },
          { "PointLight":
            {
              "@intensity":0.3,
              "@location":[0,-2,6]
            }
          },
          { "Group":
            {
              "@DEF":"AnimatedView",
              "-children":[
                { "Viewpoint":
                  {
                    "@DEF":"MovingPov",
                    "@description":"Rotating Viewpoint"
                  }
                },
                { "TimeSensor":
                  {
                    "@DEF":"PovClock",
                    "@cycleInterval":60,
                    "@loop":true
                  }
                },
                { "PositionInterpolator":
                  {
                    "@DEF":"MovingPovLocation",
                    "@key":[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1],
                    "@keyValue":[0,0,3,3,0,2,3,0,2,0,0,3,0,0,3,-3,0,2,-3,0,2,0,0,3,0,0,3]
                  }
                },
                { "ROUTE":
                  {
                    "@fromField":"fraction_changed",
                    "@fromNode":"PovClock",
                    "@toField":"set_fraction",
                    "@toNode":"MovingPovLocation"
                  }
                },
                { "ROUTE":
                  {
                    "@fromField":"value_changed",
                    "@fromNode":"MovingPovLocation",
                    "@toField":"position",
                    "@toNode":"MovingPov"
                  }
                },
                { "OrientationInterpolator":
                  {
                    "@DEF":"MovingPovRotation",
                    "@key":[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1],
                    "@keyValue":[0,1,0,0,0,1,0,0.982794,0,1,0,0.982794,0,1,0,0,0,1,0,0,
                                 0,1,0,-0.982794,0,1,0,-0.982794,0,1,0,0,0,1,0,0]
                  }
                },
                { "ROUTE":
                  {
                    "@fromField":"fraction_changed",
                    "@fromNode":"PovClock",
                    "@toField":"set_fraction",
                    "@toNode":"MovingPovRotation"
                  }
                },
                { "ROUTE":
                  {
                    "@fromField":"value_changed",
                    "@fromNode":"MovingPovRotation",
                    "@toField":"set_orientation",
                    "@toNode":"MovingPov"
                  }
                }
              ]
            }
          },
          { "Viewpoint":
            {
              "@description":"Origami Cranes, from ahead",
              "@orientation":[0,1,0,0.982794],
              "@position":[3,0,2]
            }
          },
          { "Viewpoint":
            {
              "@description":"Origami Cranes, mirror image",
              "@position":[0,0,3]
            }
          },
          { "Viewpoint":
            {
              "@description":"Origami Cranes, from behind",
              "@orientation":[0,1,0,-0.982794],
              "@position":[-3,0,2]
            }
          },
          { "Transform":
            {
              "@DEF":"CraneAbove",
              "@rotation":[0,1,0,1.745329],
              "-children":[
                { "#comment":"Rotation was necessary to point along X axis"
                },
                { "Transform":
                  {
                    "@DEF":"TranslateToOrigin",
                    "@translation":[0.25,-0.18,-0.1],
                    "-children":[
                      { "Shape":
                        {
                          "@DEF":"CraneShapeWhite",
                          "-geometry":
                            { "IndexedFaceSet":
                              {
                                "@DEF":"CraneIFS",
                                "@coordIndex":[0,1,2,-1,0,2,3,-1,4,5,2,-1,4,2,1,-1,
                                  1,0,6,-1,7,2,8,-1,3,9,10,-1,11,12,13,-1,12,9,14,-1,
                                  11,9,12,-1,15,2,7,-1,14,9,2,-1,7,10,15,-1,12,15,16,-1,
                                  13,12,16,-1,14,15,12,-1,16,17,13,-1,13,17,11,-1,
                                  15,14,2,-1,9,3,2,-1,1,6,4,-1,18,8,2,-1,5,19,20,-1,
                                  21,22,23,-1,23,24,20,-1,21,23,20,-1,25,18,2,-1,
                                  24,2,20,-1,18,25,19,-1,23,26,25,-1,22,26,23,-1,
                                  24,23,25,-1,26,22,27,-1,22,21,27,-1,25,2,24,-1,20,2,5,-1],
                                "@solid":false,
                                "-children":[
                                  { "#comment":"Original model values are quite large,
                                       converted from inches to meters using factor 0.0254 to
                                       rescale, wingtip is now 0.8m and length is 1.5m."
                                  }
                                ],
                                "-coord":
                                  { "Coordinate":
                                    {
                                      "@point":[-0.39882,0.8134,0.63626,
                                       -0.33169,0.81323,0.53558,-0.2503,0.31524,
                                       0.08395,-0.35153,0.19681,0.28621,-0.30394,
                                       0.8134,0.65336,-0.22605,0.19681,0.30883,
                                       -0.37413,0.67816,0.77105,-0.28707,0.18877,
                                       -0.12428,-0.11107,0.78537,-0.68858,-0.40796,
                                       0.34843,0.27538,-0.37208,0.32894,0.06357,
                                       -0.45279,0.43502,0.29314,-0.37197,0.32891,
                                       0.06359,-0.40743,0.43285,0.05396,-0.25021,
                                       0.52642,0.08345,-0.33581,0.34187,-0.15904,
                                       -0.36691,0.43174,-0.18336,-1.12733,0.86101,
                                       -0.07052,-0.14315,0.18877,-0.09835,-0.12906,
                                       0.32894,0.10737,-0.16939,0.34843,0.31838,
                                       -0.13358,0.43502,0.35067,-0.09258,0.43285,
                                       0.11071,-0.12918,0.32891,0.10735,-0.25021,
                                       0.52642,0.08345,-0.08534,0.34187,-0.1139,
                                       -0.0477,0.43174,-0.12584,0.62547,0.86101,0.24538]
                                    }
                                  }
                              }
                            },
                          "-appearance":
                            { "Appearance":
                              {
                                "-material":
                                  { "Material":
                                    {
                                      "@diffuseColor":[0.9,0.9,0.9]
                                    }
                                  }
                              }
                            }
                        }
                      }
                    ]
                  }
                }
              ]
            }
          },
          { "Transform":
            {
              "@DEF":"CraneBelow",
              "@rotation":[1,0,0,3.141593],
              "-children":[
                { "Transform":
                  {
                    "@rotation":[0,1,0,1.745329],
                    "-children":[
                      { "Transform":
                        {
                          "@translation":[0.25,-0.18,-0.1],
                          "-children":[
                            { "Shape":
                              {
                                "@DEF":"CraneShapeBlack",
                                "-geometry":
                                  { "IndexedFaceSet":
                                    {
                                      "@USE":"CraneIFS"
                                    }
                                  },
                                "-appearance":
                                  { "Appearance":
                                    {
                                      "-material":
                                        { "Material":
                                          {
                                            "@diffuseColor":[0.15,0.15,0.15]
                                          }
                                        }
                                    }
                                  }
                              }
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
    }
  }
}

OrigamiCranes.json

Comments are treated as a unique-key array of objects, which appears before other child elements.

Note that the two ROUTE pairs which were not adjacent in the XML encoding are now collected together.

Attributes with default values are omitted for clarity.

Issues to top

A variety of design issues continue to get investigated and addressed. Most items are now complete.

As design patterns stabilize, X3D JSON loading and round-trip testing (.x3d <==> .json) are confirming that the right design correspondences have been implemented.

Completed work

The current stylesheet implementation handles the majority of conversion issues, including the following.

TODO open issues and action items

Apparently not possible, not a problem, or not needed


Options and Invocation to top

Stylesheet options and default values:

    <xsl:param name="stripComments"><xsl:text>false</xsl:text></xsl:param>
    <xsl:param name="stripDefaultAttributes"><xsl:text>true</xsl:text></xsl:param>
    <xsl:param name="indentEnabled"><xsl:text>true</xsl:text></xsl:param>
    <xsl:param name="sourceCode"><xsl:text>strings</xsl:text></xsl:param> <!-- escaped | strings | plaintext -->
    <xsl:param name="traceEnabled"><xsl:text>false</xsl:text></xsl:param>
    <xsl:param name="traceScripts"><xsl:text>false</xsl:text></xsl:param>

X3D-Edit conversion pane The sourceCode options govern the output mode of #sourceCode code embedded in Script, ShaderPart and ShaderProgram nodes.

Note that converted JavaScript source can be broken if it contains // comment characters since any subsequent source code is effectively ignored if stuffed into a single line.

Note that X3D-Edit has an X3D Conversions: X3D to JSON panel that offers configuration of several options for testing.

XSLT stylesheets are reusable and can be invoked by a wide variety of tools and programming languages.


References to top

Essential references

Additional references


Related Work to top

John Carlson has provided numerous insights and made many contributions during this group effort. He reports:

I have created a JSON loader for X3DOM that load JSON across the WWW.
https://github.com/coderextreme/X3DJSONLD (including a Pseudocode description).
Warning: under active development! This has been tested on a number of scenes in the Web3D Examples archives. Particular caution: a number of objects are still in the global scope of JavaScript.
Suggestions and contributions are welcome. As usual, forks of the repository and pull requests for potential changes are welcome if authors agree to the license.
Now available: the X3D JSON Loader has a README and Getting Started guide for this Application Programming Interface (API). Excerpts follow.

Introducing: the X3D JSON Loader (1.0 beta) and X3D JSON Prototype Expander (1.0 alpha)

For web browser testing, a live development version of the X3D JSON loader is recommended by downloading locally or forking.

To use the JSON loader in your HTML, put:

     <script type="text/javascript" src="https://raw.githubusercontent.com/coderextreme/X3DJSONLD/master/X3DJSONLD.js"></script>

Then somewhere in the script afterwards (see index.html for example usage) call

     loadX3DJS(selector, json, url, xml);

where

Use xml.join("") when passing the xml object to createX3DFromString()

Sample code for putting Cobweb into an iframe with id cobwebframe (thank you Andreas Plesch):

    var content = xml.join("");
    var cobwebWindow = document.getElementById("cobwebframe").contentWindow ;
    var cobwebEle = cobwebWindow.document.getElementById("x3dele");
    if (typeof cobwebWindow.X3D !== 'undefined') {
            var browser = cobwebWindow.X3D.getBrowser(cobwebEle);
            browser.replaceWorld(browser.createX3DFromString(content));
            // etc.
    }

For the prototype expander, again use a live, development version (local copy recommended). (Modification ofExternProtoDeclare statements is not supported yet.) Invocation:

    <script type="text/javascript" src="https://raw.githubusercontent.com/coderextreme/X3DJSONLD/master/PrototypeExpander.js"></script>

    prototypeExpander(json, scope);

where

There is useful code you may want to look at in index.html with long form at X3DExamplesViewer.html. These pages work when the X3D Examples are installed locally.

Community-visible efforts continue to test this library in tandem with the X3dToJson outputs. Usage reports are helpful and influential, future automation of verification is also likely.

When we get the X3D JSON encoding fully stable (it is close now), future work is also under consideration. John again reports:

I have investigated auto-generating a good portion of the JSON schema to avoid a lot of work. This will not replace eventual human intervention on editing a JSON schema, but is provided to bootstrap schema efforts. This uses Jsonix. Generating data structure code from XSD using JAXB (or other) and then taking data structure and converting it to JSON schema using Jackson (or other) should be considered as an alternative. Jsonix does not provide for a good X3D JSON standard as there is a lot of differences in the mappings and in the schema each time is is run. There are ways to support patterns in JAXB (JSR-303), which doesn�t come by default with Jsonix yet. I am not sure how to implement patterns in JSON schema. This may depend on the difference between JSON regexes and XSD regexes.
It is hoped that the X3D JSON standard will inform itself of the JSON schema standard, and will not deviate too far from existing tools in hopes of easing the burden of creating a JSON schema. We should investigate Ajv and other JSON validators once we have a JSON schema.

Additional contributions:

JavaScript libraries of related interest as potential users of X3D JSON:


Tools to top

Specialized tools are in development to provide support for X3D JSON.

Many tools are available for JSON.


Contact to top

Discussions regarding X3D JSON Encoding design and usage occur on the x3d-public@web3d.org mailing list (subscribe).
Questions, suggestions, additions and comments about this X3D to JSON Stylesheet Converter page are welcome. Please send them to Don Brutzman (brutzman at nps.edu).
Master version of this X3D to JSON Stylesheet Converter description page is available at
https://www.web3d.org/x3d/stylesheets/X3dToJson.html
Master version of this X3D to JSON Stylesheet Converter itself is available at
https://www.web3d.org/x3d/stylesheets/X3dToJson.xslt
and in version control at
https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/stylesheets/X3dToJson.xslt
Updated: 5 July 2022