Relational tables hold employees and orders. XML columns hold documents. The DB2 pureXML functions sit in the middle: they build XML from columns, parse text into XML, query inside documents with XPath/XQuery, shred repeating nodes into rows, and serialize XML back into CLOB or VARCHAR for COBOL and Java. This page is a working map of the SQL/XML functions you will actually type on z/OS.
Almost every XML task is one of these:
XML values are not strings. You cannot CONCAT an XML column with LASTNAME. You serialize first, or stay in XML constructors.
| Function | What it builds |
|---|---|
| XMLELEMENT | Build an element node (NAME "tag", children). The usual wrapper for other constructors. |
| XMLATTRIBUTES | Build attributes. Only legal inside XMLELEMENT. |
| XMLFOREST | Build a sequence of element nodes from a list of expressions (column-as-element). |
| XMLCONCAT | Concatenate a variable number of XML arguments into one sequence. |
| XMLDOCUMENT | Wrap children in a document node required for stored XML documents. |
| XMLCOMMENT | Create a comment node from a string. |
| XMLPI | Create a processing-instruction node (for example xml-stylesheet). |
| XMLTEXT | Create a text node from a string. |
XMLNAMESPACES is a declaration used as an argument of XMLELEMENT or XMLFOREST, not a standalone SELECT-list function. XMLAGG is an aggregate that concatenates XML values across a group — the GROUP BY cousin of XMLCONCAT.
12345678910111213SELECT XMLELEMENT( NAME "emp", XMLNAMESPACES(DEFAULT 'http://example.org/hr'), XMLATTRIBUTES(EMPNO AS "id"), XMLCOMMENT(' sample employee '), XMLFOREST( RTRIM(FIRSTNME) AS "first", RTRIM(LASTNAME) AS "last", SALARY AS "salary" ) ) AS EMP_XML FROM DSN8C10.EMP WHERE EMPNO = '000010';
To INSERT that result into an XML column, wrap it:
12345678INSERT INTO HR.EMP_DOC (EMPNO, INFO) VALUES ('000010', XMLDOCUMENT( XMLELEMENT(NAME "emp", XMLATTRIBUTES('000010' AS "id"), XMLFOREST('CHRISTINE' AS "first", 'HAAS' AS "last") ) ));
XMLCONCAT takes a variable number of XML arguments and returns one sequence. Null arguments are skipped in the concatenation of XML values (unlike character CONCAT, where a null operand nulls the whole result). Use it to glue sibling elements you built separately.
123456SELECT XMLCONCAT( XMLELEMENT(NAME "first", RTRIM(FIRSTNME)), XMLELEMENT(NAME "last", RTRIM(LASTNAME)) ) FROM DSN8C10.EMP WHERE EMPNO = '000010';
XMLPARSE parses a character or binary string as XML and returns an XML value.
1XMLPARSE(DOCUMENT string-expression [STRIP WHITESPACE | PRESERVE WHITESPACE])
Implicit parse happens when you INSERT a string host variable into an XML column. Use explicit XMLPARSE when you need whitespace control or validation:
123INSERT INTO HR.EMP_DOC (EMPNO, INFO) VALUES (:EMPNO, XMLPARSE(DOCUMENT :XML-TEXT STRIP WHITESPACE));
DSN_XMLVALIDATE may be invoked as an argument of XMLPARSE. When you do that, IBM requires STRIP WHITESPACE.
XMLSERIALIZE turns an XML value into a serialized string of a declared type.
123XMLSERIALIZE(CONTENT xml-expression AS CLOB(2M) [VERSION '1.0'] [EXCLUDING XMLDECLARATION | INCLUDING XMLDECLARATION])
Implicit serialization on FETCH into an XML or string host variable is usually preferred: the Db2 client handles encoding. Explicit XMLSERIALIZE is for when SQL must produce a CLOB/VARCHAR, for example to CONCAT with other text or to write a file. The old XML2CLOB(expr) spelling is a compatibility synonym for XMLSERIALIZE(... AS CLOB(2G)).
XMLQUERY evaluates an XQuery expression and returns XML. You pass the document (and optional variables) with PASSING.
1234SELECT EMPNO, XMLQUERY('$d/emp/last' PASSING INFO AS "d") AS LAST_XML FROM HR.EMP_DOC WHERE XMLEXISTS('$d/emp[@id="000010"]' PASSING INFO AS "d");
PASSING names become XQuery variables without the leading $. The name must be an XML 1.0 NCName, at most 128 bytes, unique in that PASSING clause. Arguments may be XML, integer, decimal, or non-LOB character/graphic strings — not ROWID, TIMESTAMP, binary, REAL, DECFLOAT, or FOR BIT DATA.
Practice: put indexable XPath in XMLEXISTS to qualify rows. Use XMLQUERY (including FLWOR if you must construct new XML) only on the surviving rows. XMLQUERY itself is not indexable the way XMLEXISTS XPath can be.
XMLTABLE is a table function. It belongs in FROM. A row XPath identifies repeating nodes; COLUMNS maps each node to SQL types.
12345678910SELECT X.LINE_ID, X.ITEM, X.QTY FROM ORDERS O, XMLTABLE( '$d/Order/OrderLine' PASSING O.ORDER_XML AS "d" COLUMNS LINE_ID INTEGER PATH '@id', ITEM VARCHAR(40) PATH 'Item/Name', QTY INTEGER PATH 'Qty' ) AS X;
If the source is a character string, XMLPARSE it to XML before PASSING. XMLTABLE column expressions can use XQuery to shape values; keep the row expression simple XPath when you want XML index matching.
Constructor functions typically omit null relational inputs rather than emitting an empty element (XMLFOREST skips nulls). XMLQUERY can return an empty sequence; EMPTY ON EMPTY (default in the usual form) keeps that as empty XML, not SQL null. Know which you are testing: IS NULL on an XML column versus XMLEXISTS that the path found a node.
XML is a nesting-doll letter. Constructor functions fold paper into dolls (elements, attributes, comments). XMLPARSE takes a written letter and folds it into a real doll. XMLSERIALIZE unfolds the doll back into writing so a COBOL program can read it. XMLQUERY is asking “what is written on the smallest doll?” XMLTABLE dumps every small doll onto a spreadsheet row. XMLDOCUMENT is the envelope: Db2 will not file the letter in the XML drawer without an envelope.
1. What does XMLPARSE do in DB2?
2. XMLATTRIBUTES can be used:
3. Why wrap constructor output in XMLDOCUMENT before INSERT into an XML column?
4. XMLQUERY is typically used in which clause?
5. XMLTABLE returns: