Next / Previous / Contents / Shipman's homepage

10. class Sox

An instance of this class represents a writer that emits XML to a given output stream. The Cleanroom intended functions here are more rigorous statements of the interface described in Section 4.2, “The Sox class”.

sox.py
# - - - - -   c l a s s   S o x

class Sox(object):
    '''Serial XML writer.

      Exports:
        Sox(outFile):
          [ outFile is a writeable file ->
              return a new Sox instance that writes to outFile
              with an empty tag stack ]
        .outFile:    [ as passed to constructor ]

For the specification functions used below, see Section 8.5, “xml-name and Section 8.3, “content-list.

sox.py
        .start(tag, *p, **attr):
          [ if (tag is a unicode xml-name) and
            (p is a content-list) and
            (attr is a dictionary whose keys are xml-names) ->
                outFile +:= a start tag with name (tag), attributes
                    from (attr) and dict elements of p, and content
                    from non-dict elements of p
                self  :=  self with an Elt containing (tag) pushed on its
                          stack
                return an Elt containing (tag)
            else -> raise SoxError ]
        .end(elt):
          [ elt is an Elt instance ->
              if elt is the top of self's stack ->
                outFile  +:=  end tag for elt.tag
                self  :=  self with its stack popped
              else -> raise SoxError ]
        .write(*p):
          [ p is a sequence of unicode, or str values ->
              outFile  +:=  those values, with str values
                  decoded via utf-8 ]
        .leaf(tag, *p, **kw):
          [ if (tag is an xml-name) and
            (p is a content-list) and
            (kw's keys are xml-names) ->
                outFile +:= an element with name (tag), attributes
                    from (kw) and dict elements of p, and content
                    (if any) from non-dict elements of p
            else -> raise SoxError ]
        .flush():
          [ self.outFile  :=  self.outFile with all buffered output sent ]
        .cleanup():
          [ if self's stack is empty ->
              I
            else -> raise SoxError ]
        .close():
          [ if self's stack is empty ->
              self.outFile  :=  self.outFile, closed
            else -> raise SoxError ]

See Section 8.4, “valid-comment for the rules for the content of XML comments.

sox.py
        .comment(text):
          [ text is unicode or str encoded as utf-8 ->
              if text is a valid-comment ->
                self.outFile  +:=  an XML comment containing text
              else -> raise SoxError ]
        .pi(target, args):
          [ target and args are unicode or utf-8-encoded str values ->
              if (target is an xml-name) and (args does not contain
              the string "?>" ->
                self.outFile  +:=  an XML processing instruction
                    with target (target) and arguments (args)
              else -> raise SoxError ]

Here is the class's internal state.

sox.py
      State/Invariants:
        ._stack:
          [ a list of open elements as Elt instances, in the
            order they were opened ]
    '''