25. Func='xml' Accessing XML

Example 25.1

)text out='xx'

<Order Salesrep="Yrsa" Date="2006-05-05">

<CustomNumber>4711</CustomNumber>

<CustomContact>

Wilbur Jensen &amp; 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