PBToolboxAI v3 ← Site

xml — n_pbt_xml #

← Component reference · Guide contents

Write an XML element by element — opens, attributes, text, closes — with the escaping done for you, then read one back with real XPath: of_load, of_get_value, of_get_attr, of_count. PowerBuilder 10 has no XML parser; this one relies on the WebView2 engine's DOMParser and document.evaluate, called synchronously.

▶ See it live — Demo application, XML tile: the results, the code behind them and this page, side by side.


At a glance #

The build side is pure PowerScript (assembling a string needs no engine). The read side opens a hidden page on the first query. The XPath is version 1.0, as the browser evaluates it.

Quick start #

n_pbt_xml  lnv_xml

// Read : load, then query with XPath
lnv_xml.of_load('<order id="4152"><customer>Ada</customer></order>')
IF lnv_xml.of_is_valid() THEN
	MessageBox("Customer", lnv_xml.of_get_value("/order/customer"))   // Ada
	MessageBox("Id", lnv_xml.of_get_attr("/order", "id"))              // 4152
END IF

// Build : element by element, escaping done for you
lnv_xml.of_clear()
lnv_xml.of_start_element("order")
lnv_xml.of_element_attr("id", "4152")
lnv_xml.of_leaf("customer", "Ada & Co")
lnv_xml.of_end_element()
// lnv_xml.of_xml() -> <order id="4152"><customer>Ada &amp; Co</customer></order>

Properties #

MemberRole
string is_last_errorWhy the last read returned empty or a negative code: a malformed document, an XPath that matched nothing, the demo cap. Empty after a success

Build a document #

MemberRole
of_start_element (string as_name)Opens an element (elements nest: a pending start tag is closed first)
of_element_attr (string as_name, string as_value)Adds an attribute to the open element, value escaped (before any child or text)
of_element_text (string as_text)The text content of the current element, escaped
of_end_element ( )Closes the current element (empty, it is self-closing <name/>)
of_leaf (string as_name, string as_text)A whole leaf element in one call — <name>text</name>, escaped
of_clear ( ) → longEmpties the builder to start another document. Returns 0
of_xml ( ) → stringThe document as it stands: what you built or loaded (of_load), after any change — the single output, to send, store or save back. A built document needs no page (any element left open is closed) ; a loaded one is serialized by the engine. of_pretty is the indented form

Read a document (XPath) #

MemberRole
of_load (string as_xml) → longLoads an XML text (parsed by the engine's DOMParser). Returns 0 when well-formed, -5 when empty, -4 when invalid XML, -2 when the hidden page fails
of_is_valid ( ) → booleanTrue when the last of_load succeeded and a document is held
of_exists (string as_xpath) → booleanTrue when the XPath matches at least one node
of_get_value (string as_xpath) → stringThe text content of the FIRST matching node. Empty if none
of_get_attr (string as_xpath, string as_name) → stringThe value of attribute as_name on the first matching node. Empty if absent
of_count (string as_xpath) → longHow many nodes the XPath matches. 0 when none (an XPath count is never negative)
of_name (string as_xpath) → stringThe tag name of the first matching node. Empty if none
of_pretty ( ) → stringThe document as it stands — built or loaded, what of_xml returns — re-indented for reading. Empty when there is nothing, or when a built document is not well-formed

Several nodes, and the document #

MemberRole
of_get_values (string as_xpath, ref string as_values[]) → longThe text content of EVERY matching node, into as_values; returns the count. Where of_get_value returns only the first
of_get_attrs (string as_xpath, string as_name, ref string as_values[]) → longThe value of attribute as_name on EVERY matching node (the id of every row); returns the count
of_get_attr_names (string as_xpath, ref string as_names[]) → longThe names of every attribute on the first matching node (enumeration); returns the count

Modify a document #

The write side changes the loaded tree in place; of_xml returns the result. Each targets the FIRST matching node (except of_remove, which takes them all), returns 0 on success, -4 when nothing matched, -5 on an empty argument.

MemberRole
of_set_value (string as_xpath, string as_text) → longSets the text of the first matching node (its children are replaced)
of_set_attr (string as_xpath, string as_name, string as_value) → longSets (or adds) an attribute on the first matching node
of_remove_attr (string as_xpath, string as_name) → longRemoves an attribute from the first matching node
of_add_child (string as_xpath, string as_tag, string as_text) → longAppends a child element <as_tag>as_text</as_tag> under the first matching node (the child inherits the parent's namespace)
of_add_xml (string as_xpath, string as_fragment) → longGrafts an already-formed XML fragment (one or several sibling elements) under the first matching node — what of_add_child cannot do, taking only a tag and text. The fragment must be well-formed and declare any namespace it uses
of_remove (string as_xpath) → longRemoves EVERY matching node (a row, a stale branch). Returns how many were removed (never negative)

Namespaces and XSLT #

A prefixed XPath (SOAP, an enterprise API) matches nothing without a resolver: of_register_namespace binds the prefix to its URI, of_clear_namespaces forgets them all. of_transform applies an XSLT stylesheet — the engine has XSLTProcessor, PowerBuilder 10 has nothing like it.

MemberRole
of_register_namespace (string as_prefix, string as_uri) → longBinds a prefix to its namespace URI so a prefixed XPath (/s:Envelope) resolves. Returns 0, or -5 on an empty prefix. Bindings last until of_clear_namespaces or of_reset
of_clear_namespaces ( ) → longForgets every registered prefix: a prefixed XPath matches nothing again until a prefix is bound. Returns 0
of_transform (string as_xslt) → stringTransforms the loaded document with an XSLT stylesheet and returns the result as text. Empty when nothing is loaded or the stylesheet is not valid XML
// A SOAP response : bind the prefix, then query it
lnv_xml.of_load(ls_soap)
lnv_xml.of_register_namespace("s", "http://schemas.xmlsoap.org/soap/envelope/")
ls_ok = lnv_xml.of_get_value("//s:Body/result/status")

// Mutate, then read the result back
lnv_xml.of_set_value("/order/customer", "Grace")
lnv_xml.of_add_child("/order", "total", "690.50")
// Graft a whole fragment at once (of_add_child adds only one tag)
lnv_xml.of_add_xml("/order", "<lines><line sku=\"1\">A</line><line sku=\"2\">B</line></lines>")
ls_out = lnv_xml.of_xml()

The hidden page #

MemberRole
of_open ( ) → longCreates the hidden page (read side). Optional — the first read does it. Returns the handle (> 0) or a negative code
of_is_open ( ) → booleanTrue once the hidden page exists
of_close ( )Releases the hidden page. Building keeps working without it. Done for you on destroy
of_reset ( )Back to the defaults: the builder is emptied, the read state cleared

Scope. XML is read through the engine (DOMParser, XPath): n_pbt_xml opens a hidden page on the first read, unlike json, which parses in pure PowerScript. To display an XML as a collapsible tree, see xmltree.

← Component reference · Guide contents