3. Language Extensions

XML Calabash has three language extensions: “general values”, “XPointer on text”, and “transparent JSON”. Enabling any of these extensions makes the processor non-conformant. Pipelines that rely on these extensions are not likely to be interoperable with other implementations. You're encouraged to avoid them if possible. That said, they can be very useful.

3.1. General values extension

If the general values extension is enabled, variables, options, and parameters are not limited to strings. If the select expression that establishes the value of a variable, option, or parameter selects nodes from a tree, then those node values will be passed along as the value.

Consider the pipeline in Example 5.1, “Pipeline that exploits the general values extension”:

Example 5.1. Pipeline that exploits the general values extension
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="1.0">
<p:input port="parameters" kind="parameter"/>
<p:output port="result"/>
<p:serialization port="result" indent="true"/>

<p:identity>
  <p:input port="source">
    <p:inline>
      <doc>
        <para>Some <emph>text</emph> in a paragraph.</para>
      </doc>
    </p:inline>
  </p:input>
</p:identity>

<p:xslt template-name="root">
  <p:input port="stylesheet">
    <p:inline>
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                      version="2.0">

        <xsl:param name="text" required="yes"/>
        <xsl:param name="gv" required="yes"/>

        <xsl:template name="root">
          <root general-values="{$gv}">
            <xsl:sequence select="$text"/>
          </root>
        </xsl:template>
      </xsl:stylesheet>
    </p:inline>
  </p:input>
  <p:with-param name="text" select="/doc/para"/>
  <p:with-param name="gv" select="p:system-property('cx:general-values')"
                xmlns:cx="http://xmlcalabash.com/ns/extensions"/>
</p:xslt>

</p:declare-step>

In a conformant processor, the text parameter passed to the p:xslt step is a string:

<root general-values="false">Some text in a paragraph.</root>

If the general values extension is enabled, the value contains the selected subtree:

<root general-values="true">
   <para>Some <emph>text</emph> in a paragraph.</para>
</root>

The general values extension can be enabled in three ways:

  1. With the -Xgeneral-values command-line option.

  2. With the com.xmlcalabash.general-values Java system property.

  3. Or with the <extension name="general-values" value="true"/> configuration option.

A pipeline can test whether the general values extension is enabled or not with the p:system-property function using the argument cx:general-values.

3.2. XPointer on text

Note

This extension is no longer required. RFC 5147 fragment identifiers are directly supported on the fragid property of XInclude, per the XInclude 1.1 Note.

If the XPointer on text extension is enabled, the xpointer attribute on an XInclude element can be used when parse="text". The XPointer must use the text() scheme and must contain an RFC 5147 fragment identifier. Consider the following DocBook XML fragment:

<programlisting>
<xi:include href="examples/general-values.xpl" parse="text"
            xpointer="text(line=6,15;length=1081)"/>
</programlisting>

If processed with the XPointer on text extension enabled, it would produce effectively the following result:

<programlisting><![CDATA[
<p:identity>
  <p:input port="source">
    <p:inline>
      <doc>
        <para>Some <emph>text</emph> in a paragraph.</para>
      </doc>
    </p:inline>
  </p:input>
</p:identity>]]></programlisting>

Only the “length” integrity check is supported.

The XPointer on text extension can be enabled in three ways:

  1. With the -Xxpointer-on-text command-line option.

  2. With the com.xmlcalabash.xpointer-on-text Java system property.

  3. Or with the <extension name="xpointer-on-text" value="true"/> configuration option.

A pipeline can test whether the XPointer on text extension is enabled or not with the p:system-property function using the argument cx:xpointer-on-text.

3.3. Transparent JSON

If the transparent JSON extension is enabled, p:http-request, p:store, p:document, and p:data will translate automatically between JSON and XML. If JSON is returned by a web service or loaded, it will be turned into XML. If a JSON-in-XML document is sent or stored, it will be turned into textual JSON first.

Consider this JSON object:

{
  "id": "1234",
  "": "empty string",
  "foo$bar": "key contains non-name char",
  "1foo$bar": "key starts with non-name-start char",
  "x:html": "key with colon",
  "array": [1,2,3,false,null],
  "bool": false,
  "isnull": null,
  "image": {
    "url": "http://example.com/image.jpg",
    "width": 500,
    "height": 500
  },
  "<crazy&key>": "sane value",
  "\"double quotes\"": "dquoted key",
  "'single quotes'": "squoted key"
}

It can be translated into any one of five XML representations:

marklogic
<j:json xmlns:j="http://marklogic.com/json" type="object">
   <j:_003ccrazy_0026key_003e type="string">sane value</j:_003ccrazy_0026key_003e>
   <j:_ type="string">empty string</j:_>
   <j:id type="string">1234</j:id>
   <j:_0027single_0020quotes_0027 type="string">squoted key</j:_0027single_0020quotes_0027>
   <j:_0031foo_0024bar type="string">key starts with non-name-start char</j:_0031foo_0024bar>
   <j:x_003ahtml type="string">key with colon</j:x_003ahtml>
   <j:isnull type="null"/>
   <j:foo_0024bar type="string">key contains non-name char</j:foo_0024bar>
   <j:_0022double_0020quotes_0022 type="string">dquoted key</j:_0022double_0020quotes_0022>
   <j:image type="object">
      <j:height type="number">500</j:height>
      <j:width type="number">500</j:width>
      <j:url type="string">http://example.com/image.jpg</j:url>
   </j:image>
   <j:bool type="boolean">false</j:bool>
   <j:array type="array">
      <j:item type="number">1</j:item>
      <j:item type="number">2</j:item>
      <j:item type="number">3</j:item>
      <j:item type="boolean">false</j:item>
      <j:item type="null"/>
   </j:array>
</j:json>
jsonx
<j:object xmlns:j="http://www.ibm.com/xmlns/prod/2009/jsonx">
   <j:string name="&lt;crazy&amp;key&gt;">sane value</j:string>
   <j:string name="">empty string</j:string>
   <j:string name="id">1234</j:string>
   <j:string name="'single quotes'">squoted key</j:string>
   <j:string name="1foo$bar">key starts with non-name-start char</j:string>
   <j:string name="x:html">key with colon</j:string>
   <j:null name="isnull"/>
   <j:string name="foo$bar">key contains non-name char</j:string>
   <j:string name="&#34;double quotes&#34;">dquoted key</j:string>
   <j:object name="image">
      <j:number name="height">500</j:number>
      <j:number name="width">500</j:number>
      <j:string name="url">http://example.com/image.jpg</j:string>
   </j:object>
   <j:boolean name="bool">false</j:boolean>
   <j:array name="array">
      <j:number>1</j:number>
      <j:number>2</j:number>
      <j:number>3</j:number>
      <j:boolean>false</j:boolean>
      <j:null/>
   </j:array>
</j:object>
jxml
<j:object xmlns:j="http://www.xmlsh.org/jxml">
   <j:member name="&lt;crazy&amp;key&gt;">
      <j:string>sane value</j:string>
   </j:member>
   <j:member name="">
      <j:string>empty string</j:string>
   </j:member>
   <j:member name="id">
      <j:string>1234</j:string>
   </j:member>
   <j:member name="'single quotes'">
      <j:string>squoted key</j:string>
   </j:member>
   <j:member name="1foo$bar">
      <j:string>key starts with non-name-start char</j:string>
   </j:member>
   <j:member name="x:html">
      <j:string>key with colon</j:string>
   </j:member>
   <j:member name="isnull">
      <j:null/>
   </j:member>
   <j:member name="foo$bar">
      <j:string>key contains non-name char</j:string>
   </j:member>
   <j:member name="&#34;double quotes&#34;">
      <j:string>dquoted key</j:string>
   </j:member>
   <j:member name="image">
      <j:object>
         <j:member name="height">
            <j:number>500</j:number>
         </j:member>
         <j:member name="width">
            <j:number>500</j:number>
         </j:member>
         <j:member name="url">
            <j:string>http://example.com/image.jpg</j:string>
         </j:member>
      </j:object>
   </j:member>
   <j:member name="bool">
      <j:boolean>false</j:boolean>
   </j:member>
   <j:member name="array">
      <j:array>
         <j:number>1</j:number>
         <j:number>2</j:number>
         <j:number>3</j:number>
         <j:boolean>false</j:boolean>
         <j:null/>
      </j:array>
   </j:member>
</j:object>
calabash
<c:json xmlns:c="http://www.w3.org/ns/xproc-step" type="object">
   <c:pair name="&lt;crazy&amp;key&gt;" type="string">sane value</c:pair>
   <c:pair name="" type="string">empty string</c:pair>
   <c:pair name="id" type="string">1234</c:pair>
   <c:pair name="'single quotes'" type="string">squoted key</c:pair>
   <c:pair name="1foo$bar" type="string">key starts with non-name-start char</c:pair>
   <c:pair name="x:html" type="string">key with colon</c:pair>
   <c:pair name="isnull" type="null"/>
   <c:pair name="foo$bar" type="string">key contains non-name char</c:pair>
   <c:pair name="&#34;double quotes&#34;" type="string">dquoted key</c:pair>
   <c:pair name="image" type="object">
      <c:pair name="height" type="number">500</c:pair>
      <c:pair name="width" type="number">500</c:pair>
      <c:pair name="url" type="string">http://example.com/image.jpg</c:pair>
   </c:pair>
   <c:pair name="bool" type="boolean">false</c:pair>
   <c:pair name="array" type="array">
      <c:item type="number">1</c:item>
      <c:item type="number">2</c:item>
      <c:item type="number">3</c:item>
      <c:item type="boolean">false</c:item>
      <c:item type="null"/>
   </c:pair>
</c:json>
calabash-deprecated
<json type="object">
   <pair name="&lt;crazy&amp;key&gt;" type="string">sane value</pair>
   <pair name="" type="string">empty string</pair>
   <pair name="id" type="string">1234</pair>
   <pair name="'single quotes'" type="string">squoted key</pair>
   <pair name="1foo$bar" type="string">key starts with non-name-start char</pair>
   <pair name="x:html" type="string">key with colon</pair>
   <pair name="isnull" type="null"/>
   <pair name="foo$bar" type="string">key contains non-name char</pair>
   <pair name="&#34;double quotes&#34;" type="string">dquoted key</pair>
   <pair name="image" type="object">
      <pair name="height" type="number">500</pair>
      <pair name="width" type="number">500</pair>
      <pair name="url" type="string">http://example.com/image.jpg</pair>
   </pair>
   <pair name="bool" type="boolean">false</pair>
   <pair name="array" type="array">
      <item type="number">1</item>
      <item type="number">2</item>
      <item type="number">3</item>
      <item type="boolean">false</item>
      <item type="null"/>
   </pair>
</json>

This was the original format introduced when JSON support was added to p:unescape-markup. Don't use it. Automatic conversion from XML to JSON is not supported for this format.

Note that key values in a JSON object are considered unordered. There's no way to preserve the order of keys when switching between representations.

The transparent JSON extension can be enabled in three ways:

  1. With the -Xtransparent-json command-line option.

  2. With the com.xmlcalabash.transparent-json Java system property.

  3. Or with the <extension name="transparent-json" value="true"/> configuration option.

A pipeline can test whether the transparent JSON extension is enabled or not with the p:system-property function using the argument cx:transparent-json.

The desired XML flavor can be selected using the same mechanisms:

  1. With the -Xjson-flavor=flavor command-line option.

  2. With the com.xmlcalabash.json-flavor Java system property.

  3. Or with the <extension name="json-flavor" value="flavor"/> configuration option.

The flavors are “marklogic”, “jsonx”, “jxml”, “calabash”, and “calabash-deprecated”.

A pipeline can determine the current flavor with the p:system-property function using the argument cx:json-flavor.

3.4. Use XSLT 1.0

The “use XSLT 1.0” extension enables processing of XSLT 1.0 stylesheets with an XSLT 1.0 processor. See the section called “Extensions” in p:xslt.

The XSLT 1.0 extension can be enabled in three ways:

  1. With the -Xuse-xslt-10 command-line option.

  2. With the com.xmlcalabash.use-xslt-10 Java system property.

  3. Or with the <extension name="use-xslt-10" value="true"/> configuration option.

3.5. HTML serializer

If the “HTML serializer” extension is used, then all documents that are serialized with the “html” method will be serialized with the Validator.nu HTML serializer.

The HTML serializer extension can be enabled in three ways:

  1. With the -Xhtml-serializer command-line option.

  2. With the com.xmlcalabash.html-serializer Java system property.

  3. Or with the <extension name="html-serializer" value="true"/> configuration option.

A few points:

  1. This option serializes all HTML documents with the HTML serializer; it pays no attention to the version.

  2. If the Saxon configured serializer doesn't have any output destination (or if it has an unrecognized output destination), then this option has no effect. (I'm not sure it's possible to configure the Saxon serializer this way, but maybe if you're playing in the APIs…)

  3. None of the other output options (indent, doctype, etc.) have any effect when the HTML serializer is used.

3.6. Allow text results extension

If the allow text results extension is enabled, p:xquery and p:xslt steps may return atomic values and text documents (documents that aren't XML). These documents will be encoded in XML as c:result documents with a content-type attribute that identifies them as being of type “text/plain” and a cx:decode attribute with the value “true”. The p:store step will serialize them as text.