TapHome

Parsing functions

TapHome script parsing functions — PARSETEXT for text between patterns, PARSEJSON with JSONPath and PARSEXML with XPath — for reading values from device responses.

Last updated:

Parsing functions read values from text that a device returns — typically the response of an HTTP request or a received message in a Packet parser script. They accept a string, a byte collection (collection<uint8>) or a blob, work in every script and need Core 2022.2 or newer.

PARSETEXT

PARSETEXT returns the part of a text that follows a left pattern and ends before a right pattern; when that part is a number, a number is returned.

1
2
PARSETEXT(source, leftPattern)
PARSETEXT(source, leftPattern, rightPattern)
NameTypeDescription
sourcestring, collection<uint8> or blobText to search. Bytes are read as iso-8859-1.
leftPatternstringText before the value. Several parts separated by ... are found one after another.
rightPatternstring, optionalText after the value. Without it the value ends at the first character that is not a letter, a digit or . (a leading + or - is kept).

Returns — a number when the found text reads as a number (with a decimal point), otherwise the text with spaces trimmed. Null when the left pattern is not found.

When the left pattern is found but the right pattern is not, the script stops with the error Specified argument was out of the range of valid values. — it does not return Null. When the right pattern may be missing, check it with INDEXOF first (verified on Core 2026.1).

Example

# text between two patterns
PARSETEXT("Lorem ipsum dolor sit amet", "ipsum", "amet");
# Result: "dolor sit"
PARSETEXT("<temp>12.2</temp>", "<temp>", "</temp>");
# Result: 12.2
# no right pattern: value ends at the first other character
PARSETEXT("<temp>12.2</temp>", "<temp>");
# Result: 12.2
PARSETEXT("status:ok,error:none", "status:");
# Result: "ok"
# several left parts, found one after another
PARSETEXT("Lorem ipsum dolor sit amet", "ipsum...sit");
# Result: "amet"
PARSETEXT("Lorem ipsum dolor sit amet consectetur adipiscing", "ipsum...sit", "adipiscing");
# Result: "amet consectetur"
# left pattern not found
PARSETEXT("a=1", "b=");
# Result: Null

Example — right pattern that may be missing

# position of the left pattern
VAR start := INDEXOF(text, "temp=");
# leave when the right pattern is missing
IF start < 0 OR INDEXOF(COPY(text, start), ";") < 0
    RETURN(NaN);
END
# read the value between the patterns
PARSETEXT(text, "temp=", ";");

See also — INDEXOF, COPY.

PARSEJSON

PARSEJSON reads a value from JSON with a JSONPath expression; with TRUE as the third argument it returns Null instead of stopping the script when the path is not found.

1
2
PARSEJSON(json, path)
PARSEJSON(json, path, ignoreError)
NameTypeDescription
jsonstring, collection<uint8> or blobJSON text.
pathstringJSONPath. The leading $. is optional.
ignoreErrorbool, optionalTRUE (or 1): return Null when the path is not found, the JSON is invalid or json is Null. Default FALSE.

Returns — the value at the path: a string, a number or a bool. Several matches are returned as a collection. An object or an array is returned as its JSON text, which can be parsed again.

PathSelects
temperature, cloud.connectedA field, a nested field.
$.devices[0].nameA field of the first array element.
$.devices[-1:].deviceIdThe last element of an array.
$[?(@.period == 1)].priceElements whose field matches a condition.

Example — with json holding:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "firstName": "John",
  "lastName": "Doe",
  "age": 26,
  "address": {
    "streetAddress": "Naist street",
    "city": "Nara",
    "postalCode": "630-0192"
  }
}
# field at the top level
PARSEJSON(json, "firstName");
# Result: "John"
# nested field
PARSEJSON(json, "address.city");
# Result: "Nara"
PARSEJSON(json, "age");
# Result: 26
# missing path returns Null, no error
PARSEJSON(json, "address.country", TRUE);
# Result: Null

PARSEJSON(json, "address.country") without the third argument stops the script with PARSEJSON - Element not found: ‘address.country’.

Example — loop over a JSON array

With TRUE, PARSEJSON returns Null after the last element, which ends the loop:

# loop counter and collected names
VAR i := 0;
VAR names := "";
# name of the first array element
VAR name := PARSEJSON(json, "$.devices[0].name", TRUE);
WHILE !ISNULL(name)
    names := names + name + "\n";
    i := i + 1;
    # name of the next element
    name := PARSEJSON(json, "$.devices[" + TOSTRING(i) + "].name", TRUE);
LOOP
# return the collected names
names;

Errors — PARSEJSON - Element not found: ‘path’; PARSEJSON - parse error: … (invalid JSON); PARSEJSON - argument 1 is null.

PARSEXML

PARSEXML reads a value from XML with an XPath expression and returns the value of the first matching node.

1
PARSEXML(xml, xpath)

Returns — the value of the first node: a number when the text reads as a number, otherwise a string; Null when nothing matches. XPath functions return their own result, for example a number from count().

Remarks

  • Numbers in node text are read according to the language settings of the control unit. To read a number with a decimal point regardless of them, wrap the path in the XPath function number().
  • Namespaces declared in the document are registered automatically. A prefixed namespace (xmlns:dc="…") is used with its prefix; a default namespace (xmlns="…") gets the name of the element that declares it — for <DIDL-Lite xmlns="…"> write DIDL-Lite:container.
  • Documents smaller than 80 kB and compiled expressions are cached, so repeated calls on the same response are cheap.

Example — with the response holding:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?xml version="1.0"?>
<catalog>
  <book id="bk101">
    <title>XML Developer's Guide</title>
    <price>44.95</price>
  </book>
  <book id="bk102">
    <title>Midnight Rain</title>
    <price>5.95</price>
  </book>
</catalog>
# response body as XML text
VAR xml := response.Content;
# title of the second book
PARSEXML(xml, "//book[2]/title");
# Result: "Midnight Rain"
# attribute value
PARSEXML(xml, "//book[1]/@id");
# Result: "bk101"
# number() reads the price as a number with a decimal point
PARSEXML(xml, "number(//catalog/book[1]/price)");
# Result: 44.95
# count() returns the number of matching nodes
PARSEXML(xml, "count(//book)");
# Result: 2
# no match returns Null
PARSEXML(xml, "//catalog/magazine[1]/price");
# Result: Null

Example — XML with namespaces

VAR xml := response.Content;
PARSEXML(xml, "//DIDL-Lite:container[dc:title='My Playlist']/DIDL-Lite:res");

Errors — PARSEXML - parse error: … (invalid XML or XPath).

See also — SENDHTTPREQUEST, DECODE.