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.

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, build 40599).

Example

PARSETEXT("Lorem ipsum dolor sit amet", "ipsum", "amet");
# Result: "dolor sit"
PARSETEXT("<temp>12.2</temp>", "<temp>", "</temp>");
# Result: 12.2
PARSETEXT("<temp>12.2</temp>", "<temp>");
# Result: 12.2
PARSETEXT("status:ok,error:none", "status:");
# Result: "ok"
PARSETEXT("Lorem ipsum dolor sit amet", "ipsum...sit");
# Result: "amet"
PARSETEXT("Lorem ipsum dolor sit amet consectetur adipiscing", "ipsum...sit", "adipiscing");
# Result: "amet consectetur"
PARSETEXT("a=1", "b=");
# Result: Null

Example — right pattern that may be missing

VAR start := INDEXOF(text, "temp=");
IF start < 0 OR INDEXOF(COPY(text, start), ";") < 0
    RETURN(NaN);
END
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"
  }
}
PARSEJSON(json, "firstName");
# Result: "John"
PARSEJSON(json, "address.city");
# Result: "Nara"
PARSEJSON(json, "age");
# Result: 26
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:

VAR i := 0;
VAR names := "";
VAR name := PARSEJSON(json, "$.devices[0].name", TRUE);
WHILE !ISNULL(name)
    names := names + name + "\n";
    i := i + 1;
    name := PARSEJSON(json, "$.devices[" + TOSTRING(i) + "].name", TRUE);
LOOP
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>
VAR xml := response.Content;
PARSEXML(xml, "//book[2]/title");
# Result: "Midnight Rain"
PARSEXML(xml, "//book[1]/@id");
# Result: "bk101"
PARSEXML(xml, "number(//catalog/book[1]/price)");
# Result: 44.95
PARSEXML(xml, "count(//book)");
# Result: 2
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.