def addetree2xnd(ns, node, elements): # Iterate through the tree and collect which elements are encountered and how they are nested for path in iterpath(node): node = path[-1] if "Element" in type(node).__name__: (xmlns, name) = getelementname(node) if (xmlns, name) in ns.elements: xndnode = ns.elements[(xmlns, name)] else: xndnode = xnd.Element(xmlns, name) ns += xndnode elements[(xmlns, name)] = set() for attrname in list(node.keys()): if not attrname.startswith( "{") and attrname not in xndnode.attrs: xndnode += xnd.Attr(attrname, type=xsc.TextAttr) elif "ProcessingInstruction" in type(node).__name__: name = node.target if name not in ns.procinsts: ns += xnd.ProcInst(name) elif "Comment" in type(node).__name__: xndnode = "#comment" elif isinstance(node, str): if node.isspace(): xndnode = "#whitespace" else: xndnode = "#text" if len(path) >= 2: parent = path[-2] if "Element" in type(parent).__name__: parententry = elements[getelementname(parent)] parententry.add(xndnode)
def asxnd(self, model="simple"): isrequired = False node = misc.first(self[required], None) if node is not None: value = str(node).strip() if value in ("true", "yes"): isrequired = True elif value not in ("false", "no"): raise ValueError( f"value {value!r} not allowed for tag <required>") return xnd.Attr(str(self[name][0].content), "xsc.TextAttr", isrequired)
def adddtd2xnd(ns, dtd): # Appends DTD information from :obj:`dtd` to the :class:`xnd.Module` object from lxml import etree # This requires lxml (http://lxml.de/) dtd = etree.DTD(dtd) # try to guess the namespace name from the dtd xmlns = getxmlns(dtd) if len(xmlns) == 1: xmlns = next(iter(xmlns)) else: xmlns = None namegetter = operator.attrgetter("name") # Add element info elements = sorted(dtd.iterelements(), key=namegetter) for elemdecl in elements: e = xnd.Element(xmlns, elemdecl.name) # Add attribute info for this element attrs = sorted(elemdecl.iterattributes(), key=namegetter) for attrdecl in attrs: if attrdecl.name == "xmlns" or attrdecl.prefix: continue # skip namespace declarations and global attributes values = [] if attrdecl.type == "id": type = "xsc.IDAttr" else: type = "xsc.TextAttr" values = attrdecl.values() if len(values) == 1: type = "xsc.BoolAttr" values = None elif not values: values = None default = attrdecl.default_value if attrdecl.default == "required": required = True else: required = None e += xnd.Attr(name=attrdecl.name, type=type, default=default, required=required, values=values) ns += e # Iterate through the elements a second time and add model information for elemdecl in elements: if elemdecl.type == "empty": modeltype = "sims.Empty" modelargs = None elif elemdecl.type == "any": modeltype = "sims.Any" modelargs = None else: def extractcont(model): content = set() if model is not None: content.update(extractcont(model.left)) if model.name is not None: content.add(model.name) content.update(extractcont(model.right)) return content elementcontent = extractcont(elemdecl.content) if elementcontent: modelargs = [ ns.elements[(xmlns, name)] for name in elementcontent ] if elemdecl.type == "mixed": modeltype = "sims.ElementsOrText" else: modeltype = "sims.Elements" else: modelargs = [] if elemdecl.type == "mixed": modeltype = "sims.NoElements" else: modeltype = "sims.NoElementsOrText" e = ns.elements[(xmlns, elemdecl.name)] if ns.model == "simple": modeltype = modeltype == "sims.Empty" modelargs = None e.modeltype = modeltype e.modelargs = modelargs # Add entities entities = sorted(dtd.iterentities(), key=namegetter) for entdecl in entities: if entdecl.name not in ("quot", "apos", "gt", "lt", "amp") and entdecl.content and len( entdecl.content) == 1: ns += xnd.CharRef(entdecl.name, codepoint=ord(entdecl.content))