Until now I only demonstrated examples where XML content is processed without suppressing the content.

A simple suppress example

OmniMark source code
  1. process
  2.   do xml-parse
  3.     scan '<doc><title>This is a title</title>' ||
  4.          '<p>This is a paragraph.</p></doc>'
  5.     output '%c'
  6.   done
  8. element #implied
  9.   output '<%q>%c</%q>'
  11. element title
  12.   suppress
The resulting output
  1. <doc><p>This is a paragraph.</p></doc>

What we did here is sending the title element to the built-in #suppress stream. Sending data to this stream is like redirecting to the black hole /dev/null.

So we also could have written line 11 and 12 as:

OmniMark source code
  1. element title
  2.   put #suppress '%c'

Line 12 says: “Continue parsing, sending the current content to the #suppress stream”. So the title element isn’t just thrown away. If there where sub elements in the title element they would have been parsed too.

Let’s make this more clear with an other example:

OmniMark source code, extracting the title
  1. global stream titleStream
  3. process
  4.   open titleStream as file 'listoutput.txt'
  5.   do xml-parse
  6.     scan '<doc><title>This is a <i>title</i></title>' ||
  7.          '<p>This is a paragraph.</p></doc>'
  8.     suppress
  9.   done
  10.   close titleStream
  12. element #implied
  13.   output '%c'
  15. element title
  16.   using output as titleStream
  17.     output '%c'
The output result in file 'listoutput.txt'
  1. This is a title

In line 1 we declared the stream titleStream and attach this stream in line 4 to our output file ‘listoutput.txt’.

At the highest level, line 8, we send the input data to the suppress stream. In the title element rule we temporarily redirect to titleStream which is attached to our file ‘listoutput.txt’.

Because every element must have a rule, the element #implied rule is used, for the <doc> element, the <i> and <p> element.

Why is the content of the <p> element not in the output file if the #implied rule, which is used for the <p> element, has a output '%c'? Well, the redirection to titleStream is only temporarily for the element <title> and its descendants. After the <title> element is parsed, the streaming falls back to the previous stream which is the suppress stream defined on line 8.

What would have happened if we changed:

  1. element #implied
  2.   output '%c'


  1. element #implied
  2.   suppress
The output result in file 'listoutput.txt'
  1. This is a

The child element <i> in <title> is now suppressed, because the <i> element fires line 13 which now states to suppress it.

Let’s take a higher gear

In this example we extract all the division titles from an XML document, number them and indent them. I gave the titles letters to make more clear how they are nested in to each other.

file 'input.xml'
  1. <doc>
  2. <div><title>[a]</title>
  3.  <div><title>[a.a]</title>
  4.      <p>XML is fun</p>
  5.  </div>
  6.  <div><title>[a.b]</title>
  7.      <p>This is a paragraph.</p>
  8.      <div><title>[a.b.a]</title></div>
  9.      <div><title>[a.b.b]</title></div>
  10.  </div>
  11.  <div><title>[a.c]</title></div>
  12. </div>
  13. <div><title>[b]</title>
  14.  <p>More text here.</p>
  15. </div>
  16. </doc>
file 'output.txt'
  1. 1 [a]
  2.  1.1 [a.a]
  3.  1.2 [a.b]
  4.   1.2.1 [a.b.a]
  5.   1.2.2 [a.b.b]
  6.  1.3 [a.c]
  7. 2 [b]
The OmniMark script
  1. global stream listWithTitles
  2. global integer numberStack variable
  4. define string function giveNumber()
  5. as
  6.   local stream returningResult
  7.   local integer countDiv initial {0}
  8.   repeat over current elements as theElement
  9.     increment countDiv when name of
  10.       current element theElement = 'div'
  11.   again
  12.   do when countDiv > number of numberStack
  13.     set new numberStack to 1
  14.   else when countDiv = number of numberStack
  15.     increment numberStack
  16.   else when countDiv < number of numberStack
  17.     remove numberStack
  18.     increment numberStack
  19.   done
  20.   open returningResult as buffer
  21.   using output as returningResult
  22.     repeat over numberStack
  23.       output 'd' % numberStack
  24.       output '.' when not #last
  25.     again
  26.   close returningResult
  27.   return '%t' ||* (number of numberStack – 1) ||
  28.            returningResult
  31. process
  32.   open listWithTitles as file 'output.txt'
  33.   using output as #suppress
  34.     do xml-parse
  35.       scan file 'input.xml'
  36.       output '%c'
  37.     done
  38.   close listWithTitles
  40. element #implied
  41.   output '%c'
  43. element title when parent is div
  44.   using output as listWithTitles
  45.     do
  46.       output giveNumber()
  47.       output ' '
  48.       output '%c%n'
  49.     done
Rating 3.00 out of 5