Skip to content

RFC: Standardizing $: namespace escaping #161

@iMrDJAi

Description

@iMrDJAi

RFC: Standardizing $: namespace escaping

Intro

JSX has proven to be very useful when it's about writing clients for XML-based APIs. It allows constructing XML requests while keeping all the JSX templating features and syntax highlighting. My company uses this approach to communicate with our different hotel/flight suppliers that provide XML API interfaces, which is quite common in the travel industry.

To achieve all of that, we have developed our custom automatic JSX runtime (xml-jsx-runtime) that takes care of transforming the JSX syntax into XML strings.

Problem

During the development of our JSX runtime, we have run into some limitations concerning the JSX standard itself:

  • children attribute name is reserved by JSX to pass child elements. Thus, we cannot specify it in elements.
  • Elements cannot have capitalized tag names since they are treated as value-based elements.

These issues render JSX unusable in certain scenarios.

Proposal

Fortunately, a solution was found! Our technique uses a special namespace that helps escaping such forbidden tag/attribute names. We have chosen $: due to the following considerations:

  • The $ character is not valid in a namespace prefix according to the XML standard, but JSX supports it. Thus, it is meaningless and can be ignored by the parser (Not a breaking change).
  • $: is short, simple, and easy to type, which makes it a great choice for the purpose.

By adopting this, JSX will be able to process Capitalized tag names and reserved attributes by default.

Demonstration

Take a look at these examples from the xml-jsx-runtime README:

/** @jsxImportSource xml-jsx-runtime/runtime */
import { js2xml } from 'xml-js'

const xml = js2xml(
  <room adults={2} $:children={1} />
  /**
   * Or
   * <room adults={2} {...{'$:children': 1}} />
   * if you environment doesn't support XML namespaces
   */
)

console.log(xml)
/** Output:
 * <room adults="2" children="1"/>
 */
/** @jsxImportSource xml-jsx-runtime/runtime */
import { js2xml } from 'xml-js'

const xml = js2xml(
  <$:Element />
)

console.log(xml)
/** Output:
 * <Element />
 */

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions