E4X

E4X in Digital Script and cartridge JavaScript, with XML literals highlighted as markup, typed selectors, hover, attribute completion and Go to Definition

Legacy feeds, SOAP calls and export scripts often build XML with E4X, the XML syntax Rhino runs on B2C Commerce. The language server reads it as real code: literals and selectors are typed as XML and XMLList and no longer report errors

The XML literal is highlighted as markup with its holes as script. Hover explains each selector, completion after .@ offers the attributes the file's literals write, and Go to Definition jumps to where a literal writes the name. No errors are reported

Where it works

FileE4X support
.dsLiterals and selectors
Cartridge .jsLiterals and selectors
Template script (${...}, <isscript>)Selectors
.tsNone, TypeScript has no E4X

What is supported

SyntaxExample
XML literals with {expr} holesvar x = <order id={id}><item/></order>;
XMLList literals<><a/><b/></>
Comments and CDATA inside literals<note><![CDATA[a < b]]></note>
Attributesx.@id, every attribute x.@*
Descendantsx..item
Childrenx.*
Qualified namesx.ns::item
Filtersx.item.(@id == 1)
ConversionXML(text), XMLList(text)
Default namespacedefault xml namespace = soap;

Highlighting colours a literal as markup and its holes as script, and the rest of the file keeps its colours

A feed builder

cartridge/scripts/feeds/StockFeed.ds
importPackage(dw.catalog);

function buildFeed(product) {
    var feed = <feed site="SiteGenesis">
        <product id={product.ID} online="true">
            <name>{product.name}</name>
        </product>
    </feed>;
    return feed;
}

var stock = buildFeed(ProductMgr.getProduct('25502038'));
for each (var item in stock..product) {
    var id = item.@id;
    var online = item.@online;
    Logger.info('Feed product {0} online {1}', id, online);
}

feed is XML, stock..product and item.@id are XMLList, and {product.ID} inside the literal is ordinary script

Hover

Hover a selector or a name in a literal to see what it selects

Hover onShows
item.@id(E4X attribute) @id: XMLList
stock..product(E4X descendants) ..product: XMLList
x.*(E4X children) .*: XMLList
x.item.(@id == 1)(E4X filter) .(predicate): XMLList
Body in env.soap::Body(E4X qualified name) and the selector, as XMLList
XML(text)function XML(value?: any): XML
default in default xml namespace = soap;default xml namespace = namespace
<product> in a literal(E4X element) <product>
online in a literal(E4X attribute) @online
The literal itself(E4X XML literal) <feed>: XML, or (E4X XMLList literal) XMLList for <>…</>

Under the signature, each hover says in one line what the selector returns, such as every descendant with that name at any depth

Signature help

Typing XML( or XMLList( without new shows XML(value?: any): XML or XMLList(value?: any): XMLList, with a note that the call converts a string, XML or XMLList. new XML(…) and methods such as child() or appendChild() show the usual signatures of the XML type. Selectors, filters and {expr} holes inside literals show no signature help

Completion

Typing .@, .. or ns:: lists the names the file's literals write: attributes after .@, elements after .. and ns::. Each row shows E4X attribute @online or E4X element <product>. Element names also join the list after xml. and inside a filter

Names come from literals in the same file. An XML parsed from a string, such as new XML(response.text), has no literal to read names from

Go to Definition

F12 or Cmd+click on an attribute or element name, such as id in item.@id, opens where a literal in the file writes it

On this page