gavo.utils.stanxml module

A stan-like model for building namespaced XML trees.

The main reason for this module is that much of the VO’s XML mess is based on XML schema and thus has namespaced attributes. This single design decision ruins the entire XML design. To retain some rests of sanity, I treat the prefixes themselves as namespaces and maintain a single central registry from prefixes to namespaces in this module.

Then, the elements only use these prefixes, and this module makes sure that during serialization the instance document’s root element contains the namespace mapping (and the schema locations) required.

exception gavo.utils.stanxml.ChildNotAllowed[source]

Bases: Error

class gavo.utils.stanxml.Element(id=None)[source]

Bases: object

An element for serialization into XML.

This is loosely modelled after t.w.template stan.

Don’t add to the children attribute directly, use addChild or (more usually) __getitem__.

Elements have attributes and children. The attributes are defined, complete with defaults, in _a_<name> attributes as in AutoNodes. Attributes are checked.

Children are not usually checked, but you can set a _childSequence attribute containing a list of (unqualified) element names. These children will be emitted in the sequence given.

When deriving from Elements, you may need attribute names that are not python identifiers (e.g., with dashes in them). In that case, define an attribute _name_a_<att> and point it to any string you want as the attribute.

When serializing these, empty elements (i.e. those having an empty text and having no non-empty children) are usually discarded. If you need such an element (e.g., for attributes), set mayBeEmpty to True.

Since insane XSD mandates that local elements must not be qualified when elementFormDefault is unqualified, you need to set _local=True on such local elements to suppress the namespace prefix. Attribute names are never qualified here. If you need qualified attributes, you’ll have to use attribute name translation.

The content of the DOM may be anything recognized by addChild. In particular, you can give objects a serializeToXMLStan method returning strings or an Element to make them good DOM citizens.

Elements cannot harbor mixed content (or rather, there is only one piece of text).

addAttribute(attName, attValue)[source]

adds attName, attValue to this Element’s attributes when instantiated.

You cannot add _a_<attname> attributes to instances. Thus, when in a pinch, use this.

addChild(child)[source]

adds child to the list of children.

Child may be an Element, a string, or a list or tuple of Elements and strings. Finally, child may be None, in which case nothing will be added.

apply(func)[source]

calls func(node, text, attrs, childIter).

This is a building block for tree traversals; the expectation is that func does something like func(node, text, attrDict, childSequence).

bailIfBadChild(child)[source]
clone()

returns a deep copy of self.

deepcopy()[source]

returns a deep copy of self.

getChildDict()[source]
isEmpty()[source]

returns true if the current node has no non-empty children and no non-whitespace text content.

iterAttNames()[source]

iterates over the defined attribute names of this node.

Each element returned is a pair of the node attribute name and the xml name (which may be translated via _a_name_<att>

iterChildren()[source]
iterChildrenOfType(type)[source]

iterates over all children having type.

iterChildrenWithName(elName)[source]

iterates over children whose element name is elName.

This always does a linear search through the children and hence may be slow.

name_ = None
render(prefixForEmpty=None, includeSchemaLocation=True, xmlDecl=False, prolog=None)[source]

returns this and its children as a string.

shouldBeSkipped()[source]

returns true if the current node should be part of an output.

That is true if it is either non-empty or _mayBeEmpty is true. An empty element is one that has only empty children and no non-whitespace text content.

exception gavo.utils.stanxml.Error[source]

Bases: Exception

class gavo.utils.stanxml.NSRegistry[source]

Bases: object

A container for a registry of namespace prefixes to namespaces.

This is used to have fixed namespace prefixes (IMHO the only way to have namespaced attribute values and retain sanity). The class is never instantiated. It is used through the module-level method registerPrefix.

classmethod addNamespaceDeclarations(root, prefixes, prefixForEmpty=None, includeSchemaLocation=True)[source]

adds xmlns declarations for prefixes to the stanxml node root.

With stanxml and the global-prefix scheme, xmlns declarations only come at the root element; thus, root should indeed be root rather than some random element.

classmethod addNamespaceDeclarationsETree(root, prefixes, prefixForEmpty=None, includeSchemaLocation=True)[source]

adds xmlns declarations for prefixes to the etree node root.

With stanxml and the global-prefix scheme, xmlns declarations only come at the root element; thus, root should indeed be root rather than some random element.

Deprecated, don’t use ElementTree with stanxml any more.

classmethod getNSForPrefix(prefix)[source]
classmethod getPrefixForNS(ns)[source]
classmethod getPrefixInfo(prefix)[source]
classmethod getSchemaForNS(ns)[source]
classmethod registerPrefix(prefix, ns, schemaLocation)[source]
class gavo.utils.stanxml.NillableMixin[source]

Bases: object

An Element mixin making the element XSD nillable.

This element will automatically have an xsi:nil=”true” attribute on empty elements (rather than leave them out entirely).

This overrides apply, so the mixin must be before the base class in the inheritance list.

apply(func)[source]
isEmpty()[source]
class gavo.utils.stanxml.Stub(dest)[source]

Bases: object

A sentinel class for embedding objects not yet existing into stanxml trees.

These have a single opaque object and need to be dealt with by the user. One example of how these can be used is the ColRefs in stc to utype conversion.

Stubs are equal to each othter if their handles are identical.

apply(func)[source]

does nothing.

Stubs don’t have what Element.apply needs, so we don’t even pretend.

getChildDict()[source]
isEmpty()[source]
iterAttNames()[source]
name_ = 'stub'
shouldBeSkipped()[source]
text_ = None
gavo.utils.stanxml.escapeAttrVal(val)[source]
gavo.utils.stanxml.escapePCDATA(val)[source]
gavo.utils.stanxml.getPrefixInfo(prefix)
gavo.utils.stanxml.registerPrefix(prefix, ns, schemaLocation)
gavo.utils.stanxml.schemaURL(xsdName)[source]

returns the URL to the local mirror of the schema xsdName.

This is used by the various xmlstan clients to make schemaLocations.

gavo.utils.stanxml.xmlrender(tree, prolog=None, prefixForEmpty=None)[source]

returns a unicode object containing tree in serialized forms.

tree can be any object with a render method or some sort of string. If it’s a byte string, it must not contain any non-ASCII.

If prolog is given, it must be a string that will be prepended to the serialization of tree. The way ElementTree currently is implemented, you can use this for xml declarations or stylesheet processing instructions.

gavo.utils.stanxml.xmlwrite(root, outputFile, prefixForEmpty=None, nsRegistry=<class 'gavo.utils.stanxml.NSRegistry'>, xmlDecl=True, includeSchemaLocation=True, prolog=None)[source]

writes an xmlstan tree starting at root to outputFile.

prefixForEmpty is a namespace URI that should have no prefix at all.

outputFile must be opened in binary mode.