.. _xmlobject-py: ############ xmlobject.py ############ ************************ class XmlObject(object): ************************ Base class for SIMO XML definitions has two properties: xml and schema. The typedef schema will be included into the schema document if the schema has an include-element. When the schema is set, a parser is generated which is used to parse and validate the xml document when setting the xml property. The textual representations are returned schema and xml properties. Successfully setting the xml property generates the object representation of the xml as well. This is taken care of by the subclass implementations of the __xml_to_obj method. def __init__(self, typedefschema): ================================== A class instance is initalized with a type definition schema:: >>> from simo.builder.xmlobject import XmlObject >>> s = ''' ... ... ... ... ... ... ... ... ''' >>> xo = XmlObject(s) >>> xo.typedef_schema[:10] '>> xo.all_ok False def __set_schema(self, schematext): =================================== Invalid schema leads to None value for schema property:: >>> s = ''' ... ... ... ... ''' >>> xo.schema = s # doctest: +ELLIPSIS Traceback (most recent call last): ... XMLSchemaParseError: Element '{http://www.w3.org/2001/XMLSchema}element': The content is not valid. Expected is (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))., line 3 >>> xo.schema Valid schema document is stored as text into the schema property:: >>> s = ''' ... ... ''' >>> xo.schema = s >>> xo.schema[:10] '>> xo.all_ok False A schema containing an include will inherit the contents of the typedef_schema, the schema text will retain the include element, but the parser will have the types defined in the typedef document:: >>> s = ''' ... ... ... ''' >>> xo.schema = s >>> 'xs:include' in xo.schema True The include must be for the document Typedefs_SIMO.xsd, other references will generate an error:: >>> snot = ''' ... ... ... ''' >>> xo.schema = snot #doctest: +ELLIPSIS Traceback (most recent call last): ... XMLSchemaParseError: ...ailed to load...some_other_def.xsd... >>> xo.schema = s def __set_xml(self, xmldata): ============================= With valid schema and xml a dictionary entry is created with the given name as key and the xml text as data:: >>> xo.xml = ('testdata', '1 2 3', None) >>> xo.xml {'testdata': '1 2 3'} >>> xo.ok['testdata'] True >>> xo.all_ok True With invalid xml, no entry is created in the xml dictionary:: >>> xo.xml = ('notvalid', 'test', None) Traceback (most recent call last): ... ValueError: Element 'nottest': No matching global declaration available for the validation root. >>> xo.xml = ('notvalideither', 'a b c', None) Traceback (most recent call last): ... ValueError: Element 'test': 'a' is not a valid value of the local union type. >>> xo.xml {'testdata': '1 2 3'} >>> xo.ok['testdata'] True >>> xo.all_ok True Changing the schema invalidates the state of the typedef-schema-xml combination, unless the set schema is identical to the current one. However, the xml content is kept intact:: >>> s = xo.schema >>> xo.schema = s >>> xo.xml {'testdata': '1 2 3'} >>> xo.ok['testdata'] True >>> s1 = '' >>> xo.schema = s1 >>> xo.xml {'testdata': '1 2 3'} >>> xo.ok['testdata'] False >>> xo.all_ok False def xml_to_obj(self, root, lexicon): ==================================== Converts the XML representation to an object instance. For those XML documents that are tied to the SIMO lexicon definition; i.e., containing variable and data level definitions, the lexicon object instance is used to validate the XML document content against the lexicon content. If the XML to object conversion is unsuccessful, the ok property for the XML name will be set to False as well as the all_ok property. If it is successful, the ok property for the XML name will be set to True, and all the other entries in the ok property will be scanned for False values. If none are found, the all_ok property will be set to True as well. Each subclass of XmlObject will provide an implementation for this method. def reparse(self, lexicon=None): ================================ Used to explicitly parse the schema and xml content again after typedef or schema changes:: >>> s = ''' ... ... ''' >>> xo.schema = s >>> tds = ''' ... ... ... ... ''' >>> xo.typedef_schema = tds >>> xo.all_ok False >>> xo.ok['testdata'] False >>> xo.reparse() >>> xo.ok['testdata'] True >>> xo.all_ok True >>> 'doopidoo' in xo.typedef_schema True >>> 'xs:string' in xo.schema True def level_ind(self, level): =========================== Checks whether a lexicon is defined, and whether the level can be found in the lexicon. Logs an error message if either of these fail and returns None, else returns the level index number for data matrix:: >>> xo.lexicon >>> xo.errors set([]) >>> xo.from_module = 'testmodule' >>> xo.level_ind('comp_unit') >>> xo.errors set(["No lexicon set when validating level for testmodule 'testdata'"]) >>> class Lexicon(object): ... def get_level_ind(self, level): ... if level == 'comp_unit': return 1 ... else: return None ... def get_variable_ind(self, level, var, active=False): ... if level == 'comp_unit' and var == 'TS': ... return (1, 1) ... else: ... return (None, None) >>> xo.lexicon = Lexicon() >>> xo.clear_warnings_and_errors() >>> xo.level_ind('comp_unit') 1 >>> xo.errors set([]) >>> xo.level_ind('non existing') >>> xo.errors set(["Level 'non existing' not found in lexicon for testmodule 'testdata'"]) def variable_ind(self, level, var): =================================== Checks whether a lexicon is defined, and whether the variable at the given level can be found in the lexicon. Logs an error message if either of these fail and returns (None, None), else returns a tuple of level index and variable index for the data matrix:: >>> xo.variable_ind('comp_unit', 'TS') (1, 1) >>> xo.variable_ind('comp_unit', 'X') (None, None) >>> xo.errors set(["Variable 'X' not found at level 'comp_unit' in lexicon for testmodule 'testdata'", "Level 'non existing' not found in lexicon for testmodule 'testdata'"]) def elem_namespace(elemtag): ============================ Returns the namespace of an XML element:: >>> from lxml import etree >>> root = etree.fromstring('') >>> xo.elem_namespace(root.tag) '{http://www.simo-project.org/simo}' def elem_name(elemtag): ======================= Returns the tag name of an XML element:: >>> xo.elem_name(root.tag) 'root' def add_warning(self, msg): =========================== Appends the message into the list contained in the warnings attribute. def add_error(self, msg): ========================= Adds the error message into the set contained in the errors attribute. def clear_warnings_and_errors(self): ==================================== >>> xo.clear_warnings_and_errors() >>> xo.warnings [] >>> xo.errors set([])