Field definitions in JXT are the entries in the fields
section of a definition:
registry.define({
namespace: 'test',
element: 'x',
path: 'example',
fields: {
// Field definitions are here
}
});
Each field can include an importer()
and exporter()
function, where the importer()
function is responsible for converting an XML object into JSON, and exporter()
is used to convert JSON to XML:
type FieldImporter = (xml: XMLElement, context: TranslationContext) => any;
type FieldExporter = (xml: XMLElement, data: any, context: TranslationContext) => void;
interface FieldDefinition {
importer: FieldImporter;
exporter: FieldExporter;
}
The importer()
is given the source XML element, and is expected to return whatever value should be assigned to the field name.
The exporter()
object is given the XML element that is being expanded, the current value of the field. The exporter()
does not return anything, it is expected to modify the given XML element in-place.
The TranslationContext
can be used to access information such as the languages to accept, the current key path, the JXT registry being used, etc.
In nearly all cases, you will use a function to create field definitions dynamically. Here is an example implementation of a field that gets/sets data from an attribute.
const attributeField = (attrName: string): FieldDefinition => ({
importer(xml: XMLElement) {
return xml.getAttribute(attrName);
},
exporter(xml: XMLElement, value: string) {
xml.setAttribute(attrName, value);
}
});
This attributeField()
function can now be used in a JXT definition:
registry.define({
namespace: 'test',
element: 'x',
path: 'example',
fields: {
attribute: attributeField('someAttrName')
}
});
JXT comes bundled with a variety of pre-defined field definitions. These definitions come in several flavors:
-
[type]Attribute()
Map and cast an attribute value to the given type (boolean, integer, etc).
-
namespaced[Type]Attribute
Same as
[type]Attribute
, but the attribute also uses an XML namespace. -
child[Type]Attribute
The same as
[type]Attribute
, but the attribute is on a child XML element. -
child[Type]
Map a value from a child XML element, and cast to the given type.
-
multipleChild[Type]
Similar to
child[Type]
, but maps an array of values. -
childLanguage[Type]
Similar to
child[Type]
, but the child element that is used is based on the current language.The language used when exporting can be found in the
lang
property of theTranslationContext
, and the set of languages to consider when importing can be found in theacceptLanguages
property. -
childAlternateLanguage[Type]
Alternate language definitions use a dictionary mapping language codes to desired values. This definition kind should be used along side
childLanguage[Type]
to capture all available language-based values in addition to the "default" provided bychildLanguage[Type]
.
Some of these definitions can accept a defaultValue
parameter. When a default value is given, it is only applied when importing from XML to JSON. The default value will not be applied to any exported XML.
attribute(name: string, defaultValue?: string, emitEmpty?: boolean)
Parameter | Type | Description |
---|---|---|
name | string |
The name of the attribute |
defaultValue | string | undefined |
Default value to use if the attribute is not present, or is empty. |
emitEmpty | boolean | undefined |
In some cases, the attribute value "" instead of eliding the attribute is desired. |
Returns: string
booleanAttribute(name: string)
Parameter | Type | Description |
---|---|---|
name | string |
The name of the attribute |
Returns: boolean
childAlternateLanguageRawElement(namespace: string | null, element: string, sanitizer?: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
sanitizer | string |
The name of a sanitizer function to remove any potentially harmful elements or attribute values (e.g. <script/> elements or javascript: URIs). Sanitizers SHOULD act as whitelists and only pass through approved elements. |
Returns: Array<{ lang: string, value: JSONElement }>
NOTE: The named sanitizer MUST be present in the
sanitizers
property of theTranslationContext
in order for any data to be returned.
A JSONElement
value is defined as:
interface JSONElement {
name: string;
attributes: {
[key: string]: string;
};
children: Array<JSONElement | string>;
}
This interface is slightly different than the XMLElement
type used when importing and exporting. It purposefully does not include the parent
property so that there are no circular references, making the imported data usable with JSON.stringify()
.
childAlternateLanguageText(namespace: string | null, element: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
Returns: Array<{ lang: string, value: string }>
childAttribute(namespace: string | null, element: string, name: string, defaultValue?: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
name | string |
The name of the attribute |
defaultValue | string | undefined |
Default value to use if the attribute is empty or not present |
Returns: string
childBoolean(namespace: string | null, element: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
Returns: boolean
childBooleanAttribute(namespace: string | null, element: string, name: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
name | string |
The name of the attribute |
Returns: boolean
childDate(namespace: string | null, element: string, useCurrentDate: boolean = false)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
useCurrentDate | boolean | undefined |
If set to true , the current date will be used when importing if the child element does not contain a date value. |
Returns: Date
NOTE: The date value in the XML MUST be parsable by the JavaScript
Date
constructor. The exported data value will be in ISO format.
childDateAttribute(namespace: string | null, element: string, name: string, useCurrentDate: boolean = false)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
name | string |
The name of the attribute |
useCurrentDate | boolean | undefined |
If set to true , the current date will be used when importing if the child element does not contain a date value. |
Returns: Date
NOTE: The child element's text value MUST be parsable by the JavaScript
Date
constructor. The exported data value will always be in ISO format.
childEnum(namespace: string | null, elements: Array<string | [string, string]>, defaultValue?: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
elements | `Array<string | [string, string]>` |
defaultValue | string | undefined |
Default value to use if there are no child elements whose name is in elements |
Returns: string
childFloat(namespace: string | null, element: string, defaultValue?: number)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
defaultValue | number | undefined |
Default value to use if the attribute is empty or not present |
Returns: number
childFloatAttribute(namespace: string | null, element: string, name: string, defaultValue?: number)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
name | string |
The name of the attribute |
defaultValue | number | undefined |
Default value to use if the attribute is empty or not present |
Returns: number
childInteger(namespace: string | null, element: string, defaultValue?: number)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
defaultValue | number | undefined |
Default value to use if the attribute is empty or not present |
Returns: number
NOTE: When importing, the child element text is parsed using
parseInt()
with a radix of10
.
childIntegerAttribute(namespace: string | null, element: string, name: string, defaultValue?: number)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
name | string |
The name of the attribute |
defaultValue | number | undefined |
Default value to use if the attribute is empty or not present |
Returns: number
NOTE: When importing, the child attribute text is parsed using
parseInt()
with a radix of10
.
childJSON(namespace: string | null, element: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
Returns: any
The JSON object assigned to the field will be serialized and set as the child element's text content.
childLanguageAttribute(namespace: string | null, element: string)
Returns: string
This definition is specifically for getting or setting the value of the xml:lang
attribute of a child element.
If no xml:lang
attribute is present on the child element when importing, it will search up the XML tree until an xml:lang
is found. If none is found, the lang
value provided in the TranslationContext
will be used.
The current language when exporting data is normally controlled by defining a field named lang
whose field type is languageAttribute()
. You can assign the field type childLanguageAttribute()
to the lang
field instead if you wish to change the current language based on the child element's language:
registry.define({
namespace: 'test',
name: 'alt-lang-location',
fields: {
lang: childLanguageAttribute(null, 'child-with-lang')
}
});
In most cases, you will want to use the field name lang
so that the current language in the TranslationContext
is correctly set during export. However, if you need to use a different field name, set the languageField
property when creating the JXT definition to the alternate field name:
registry.define({
namespace: 'test',
name: 'alt-lang-location',
languageField: 'theLanguageToUse',
fields: {
theLanguageToUse: childlanguageAttribute(null, 'child-with-lang')
}
});
childLanguageRawElement(namespace: string | null, element: string, sanitizer?: string)
childRawElement(namespace: string | null, element: string, sanitizer?: string)
childText(namespace: string | null, element: string, defaultValue?: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
defaultValue | string |
The default value to use when there is no text content for the element |
Returns: string
If there are multiple child elements with the given name, the following will be checked:
- If the
acceptLanguages
property of theTranslationContext
is set, the first child element whose language value appears earliest in the list will be used. - If there is no
acceptLanguages
set, or no child elements have a language matchingacceptLanguages
, the first child whose language matches the current language in the context (lang
inTranslationContext
) will be used. - If no child has a matching language, the first child will be used.
- If there are no children, the default value will be used.
NOTE: It is advisable to also use
childAlternateLanguageText()
to capture all available language data.
childTextBuffer(namespace: string | null, element: string, encoding: string = 'utf8')
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
encoding | string |
The encoding to use for the buffer |
Returns: Buffer
childTimezoneOffset(namespace: string | null, element: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
Returns: number
The timezone offset is the provided as the number of minutes (positive or negative) from UTC.
The child element text MUST be formatted as +HH:MM
or -HH:MM
.
dateAttribute(name: string, useCurrentDate: boolean = false)
Parameter | Type | Description |
---|---|---|
name | string |
The name of the attribute |
useCurrentDate | boolean | undefined |
If set to true , the current date will be used when importing if the child element does not contain a date value. |
Returns: Date
NOTE: The date value in the XML MUST be parsable by the JavaScript
Date
constructor. The exported data value will be in ISO format.
floatAttribute(name: string, defaultValue?: number)
Parameter | Type | Description |
---|---|---|
name | string |
The name of the attribute |
defaultValue | number | undefined |
Default value to use if the attribute is empty or not present |
Returns: number
integerAttribute(name: string, defaultValue?: number)
Parameter | Type | Description |
---|---|---|
name | string |
The name of the attribute |
defaultValue | number | undefined |
Default value to use if the attribute is empty or not present |
Returns: number
NOTE: When importing, the attribute text is parsed using
parseInt()
with a radix of10
.
languageAttribute();
Returns: string
This definition is specifically for getting or setting the value of the xml:lang
attribute.
If no xml:lang
attribute is present when importing, it will search up the XML tree until an xml:lang
is found. If none is found, the lang
value provided in the TranslationContext
will be used.
In most cases, you will want to use the field name lang
with this definition type so that the current language in the TranslationContext
is correctly set during export.
However, if you need to use a different field name for language, set the languageField
property when creating the JXT definition to the alternate field name:
registry.define({
namespace: 'test',
name: 'alt-lang-location',
languageField: 'theLanguageToUse',
fields: {
theLanguageToUse: languageAttribute()
}
});
multipleChildAlternateLanguageText(namespace: string | null, element: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
Returns: Array<{ lang: string, value: string[]}>
multipleChildAttribute(namespace: string | null, element: string, name: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
name | string |
The name of the attribute |
Returns: string[]
multipleChildEnum(namespace: string | null, elements: Array<string>)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
elements | `Array<string | [string, string]>` |
Returns: string[]
multipleChildText(namespace: string | null, element: string)
Parameter | Type | Description |
---|---|---|
namespace | string | null |
The namespace of the child element. If null , the parent namespace will be used. |
element | string |
The name of the child element |
Returns: string[]
If there are multiple child elements with the given name, but different languages, the following will be checked:
- If the
acceptLanguages
property of theTranslationContext
is set, the children whose language value appears earliest in the list will be used. - If there is no
acceptLanguages
set, or no child elements have a language matchingacceptLanguages
, the children whose language matches the current language in the context (lang
inTranslationContext
) will be used. - Otherwise, an empty list is returned.
NOTE: It is advisable to also use
multipleChildAlternateLanguageText()
to capture all available language data.
namespacedAttribute(prefix: string, namespace: string, name: string, defaultValue?: string)
Parameter | Type | Description |
---|---|---|
prefix | string |
The namespace prefix to use if the namespace has not already been declared |
namespace | string |
The namespace of the attribute |
name | string |
The name of the attribute |
defaultValue | string |
The default value to use when there is no text content for the element |
Returns: string
namespacedBooleanAttribute(prefix: string, namespace: string, name: string)
Parameter | Type | Description |
---|---|---|
prefix | string |
The namespace prefix to use if the namespace has not already been declared |
namespace | string |
The namespace of the attribute |
name | string |
The name of the attribute |
Returns: boolean
namespacedDateAttribute(prefix: string, namespace: string, name: string, useCurrentDate: boolean = false)
Parameter | Type | Description |
---|---|---|
prefix | string |
The namespace prefix to use if the namespace has not already been declared |
namespace | string |
The namespace of the attribute |
name | string |
The name of the attribute |
useCurrentDate | boolean |
The default value to use when there is no text content for the element |
Returns: Date
NOTE: The date value in the XML MUST be parsable by the JavaScript
Date
constructor. The exported data value will be in ISO format.
namespacedFloatAttribute(prefix: string, namespace: string, name: string, defaultValue?: number)
Parameter | Type | Description |
---|---|---|
prefix | string |
The namespace prefix to use if the namespace has not already been declared |
namespace | string |
The namespace of the attribute |
name | string |
The name of the attribute |
defaultValue | number |
The default value to use when there is no text content for the element |
Returns: number
namespacedIntegerAttribute(prefix: string, namespace: string, name: string, defaultValue?: number)
Parameter | Type | Description |
---|---|---|
prefix | string |
The namespace prefix to use if the namespace has not already been declared |
namespace | string |
The namespace of the attribute |
name | string |
The name of the attribute |
defaultValue | number |
The default value to use when there is no text content for the element |
Returns: number
NOTE: When importing, the child element text is parsed using
parseInt()
with a radix of10
.
splicePath(namespace: string | null, element: string, path: string, multiple?: boolean)
staticValue(value: any)
Parameter | Type | Description |
---|---|---|
value | any |
The value to always return |
Returns: string
The staticValue()
type is used to inject a value into the imported data, but has no effect when exporting.
text(defaultValue?: string)
Parameter | Type | Description |
---|---|---|
defaultValue | string |
The default value to use when there is no text content for the element |
Returns: string
textBuffer(encoding: string = 'utf8')
Parameter | Type | Description |
---|---|---|
encoding | string |
The encoding to use for the buffer |
Returns: Buffer