Example 25.1
)text out='xx'
<Order Salesrep="Yrsa" Date="2006-05-05">
<CustomNumber>4711</CustomNumber>
<CustomContact>
Wilbur Jensen & John Doe
</CustomContact>
<ShippingAddress A1="Solitudevej 14" A2="2840 Holte"/>
<Detail>
<Itemno>1864</Itemno>
<Quantity>4</Quantity>
</Detail>
<Detail>
<Itemno>1448</Itemno>
<Quantity>2</Quantity>
</Detail>
</Order>
)endtext
)action in='xx'
)& func='xml'
do i = 1 to xml.0
if i > xml_elem_unch then do
intend = left(' ',i * 2)
if i < xml.0 | xml = '' then do
intend""xml.i
end
else do
intend""xml.i "=" xml
end
end
end
do i = 1 to xml_attrib.0
intend" "xml_attrib.i"="value(xml_attrib.i)
end
)endaction
Output is:
Order
Salesrep=Yrsa
Date=2006-05-05
CustomNumber = 4711
CustomContact = Wilbur Jensen & John Doe
ShippingAddress
A1=Solitudevej 14
A2=2840 Holte
Detail
Itemno = 1864
Quantity = 4
Detail
Itemno = 1448
Quantity = 2
The RXS function value (third last line) performs a double de-reference: xml_attrib.i holds a name of a variable as a value, and the value of this variable is found.
Notice that XML is a 'generalized' language. Accordingly, the above RXS program (the second action block) will format (or de-format) any XML structure.
func='xml' presumes input is ‘well formed' XML. Otherwise execution is terminated in error.
The input file is considered as being one single piece of XML, containing just one starting tag that is closed in the last record.
The input XML structure for an action block using func='XML' triggers the action block every time the XML structure assigns values for one or more variables. That is, every time an element is assigned a value, or some attributes at the same level are assigned values, or both.
'Escape sequences' in the XML are translated to their equivalent characters (notice the element in CustomContact in Example 25.1 above).
'White space' around elements is ignored (again notice the element in CustomContact in Example 25.1 above).
The following RXS variables are assigned values in the triggering:
xml.i |
A stem containing the hierarchy of names behind the actual value. xml.0 contains the number of elements in the stem, that is, the number of names in the actual hierarchy. 'XML namespace' is ignored: When namespace is used, only the part of the name behind ':' is recorded. |
xml_cnt |
The number of names in the actual hierarchy (equal to xml.0) |
xml_attrib.i |
A stem containing names of all attributes that are assigned a value at this level in the hierarchy. xml_attrib.0 contains the number of elements in the stem, that is the number of attributes at this level in the hierarchy. 'XML namespace' is ignored: When namespace is used, only the part of the name behind ':' is recorded |
xml_attrib_cnt |
The number of attributes at this level in the hierarchy (equal to xml_attrib.0) |
xml |
The value of the element (might be content of a CDATA string in the XML) |
xml_elem_unch |
The number of names in the current hierarchy that belong to the same path compared to the previous triggering of the action block. That is: elements numbered from 1 up to xml_elem_unch are part of the same path as in the previous triggering. |
Besides these variables, attributes are at hand inside the action block. If for instance the actual path in the XML contains the assignment yrsa = "14", the variable yrsa will contain the value 14.
Notice: RXS is not case sensitive; accordingly attributes Yrsa and yrsa are considered the same variable
If the actual path in the XML only assigns values to attributes, xml is empty (is a string of length zero).
If the actual path in the XML only assigns value to the element, then xml_attrib_cnt and xml_attrib.0 is zero.
Attributes given value in a former triggering, are empty (string of length zero) in the actual triggering - unless the current path in XML assigns new values to these.
Referring to example 25.1: in the first triggering of the action block xml.1 contains "Order", xml.2 contains "Salesrep" and xml contains "Yrsa". xml_elem_unch is zero.
In the second triggering of the action block xml.1 contails "Order", xml.2 contains "Date" and xml contains "2005-05-05". xml_elem_unch contains 1 indicating that only first element in xml. is unchanged compared to the first triggering.
Constraints:
In example 25.1 following values are assigned during the seven triggerings of the action block:
xml.1 |
xml.2 |
xml.3 |
xml.0 |
xml |
xml_elem_unch |
Order |
- |
- |
1 |
- |
0 |
Order |
CustomNumber |
- |
2 |
4711 |
1 |
Order |
ShippingAddress |
- |
2 |
- |
1 |
Order |
Detail |
Itemno |
3 |
1864 |
1 |
Order |
Detail |
Quantity |
3 |
4 |
2 |
Order |
Detail |
Itemno |
3 |
1448 |
1 |
Order |
Detail |
Quantity |
3 |
2 |
2 |
Besides, attributes are given values.
Example 25.2
The input in this example is one file containing a sequence of separate xml-structures.
)text out='xx'
<order no="1"><type>Pizza No 14</type><quant>3</quant></order>
<order no="3"><type>Slush Ice</type><quant>2</quant></order>
)endtext
)action in='xx' /* separate input */
)& i=0
i = i + 1
indv = unit.1
)action out='q'i
indv
)endaction
)endaction
)action /* read the separated input */
do ii = 1 to i
'-------------- XML-structure number ' ii '---------------'
)action in='q'ii
)& func='xml'
do i = 1 to xml.0
if i > xml_elem_unch then do
intend = left(' ',i * 2)
if i < xml.0 | xml = '' then do
intend""xml.i
end
else do
intend""xml.i "=" xml
end
end
end
do i = 1 to xml_attrib.0
intend" "xml_attrib.i"="value(xml_attrib.i)
end
)endaction
end
)endaction
The first action block (marked with /* separate input */) puts every single input record into a separate queue, named 'q1', 'q2', 'q3' and so forth. The variable i contains the total number of queues.
The next top-level action block (marked with /* read the separated input */) reads these queues one after one, and analyzes them as XML.
Output is:
---------------- XML-structure number 1 ---------------
order
no=1
type=Pizza No 14
quant=3
---------------- XML-structure number 2 ---------------
order
no=3
type=Slush Ice
quant=2